#pragma once
#include <vector>
#include <string>
#include <map>

#include "Mission.h"

/**
 * An expression that checks if a mission may be accepted or not
 */
class PrerequisiteExpression final
{
	bool m_or;
	uint32_t a;
	uint32_t sub;
	PrerequisiteExpression* b;

public:
	/**
	 * Executes the prerequisite, checking its contents and returning whether or not the mission may be accepted
	 * @param missions the list of missions to check the prerequisites against (f.e. whether they're completed)
	 * @return whether or not all the prerequisites are met
	 */
	bool Execute(const std::unordered_map<uint32_t, Mission*>& missions) const;

	explicit PrerequisiteExpression(const std::string& str);
	~PrerequisiteExpression();
};

/**
 * Utility class for checking whether or not a mission can be accepted using its prerequisites
 */
class MissionPrerequisites final
{
public:
	/**
	 * Checks whether or not the mission identified by the specified ID can be accepted based on the mission inventory passed.
	 * Also performs checks for daily missions (e.g. if the time out is valid).
	 * @param missionId the mission ID to check prerequisites for
	 * @param missions the mission inventory to check the prerequisites against
	 * @return whether or not the mission identified by the specified ID can be accepted
	 */
	static bool CanAccept(uint32_t missionId, const std::unordered_map<uint32_t, Mission*>& missions);
private:

	/**
	 * Cache of all the executed prerequisites
	 */
	static std::unordered_map<uint32_t, PrerequisiteExpression*> expressions;

	/**
	 * Checks the prerequisites for a mission
	 * @param missionId the mission ID to check prerequisites for
	 * @param missions the mission inventory to check the prerequisites against
	 * @return whether or not the mission identified by the specified ID can be accepted
	 */
	static bool CheckPrerequisites(uint32_t missionId, const std::unordered_map<uint32_t, Mission*>& missions);
};