#pragma once
#include "BaseModel.h"
#include "ConstructionTask.h"
#include "TrainingTask.h"
#include "ScoutTask.h"
#include "InternalStateChangeTask.h"
#include "ResearchTask.h"
#include "GuardTask.h"
#include "Overseer.h"
#include "BWAPI.h"
#include "BWTA.h"
#include <stack>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <deque>
using namespace BWTA;
using namespace BWAPI;

class ExpandTask;

/*
	The main idea behind this architecture is as follows:
		Each base has associated with it a template. The template acts to describe the conditions
		under which construction tasks are instantiated within the base. Specifically this concerns
		primarily the construction of economy-based buildings, like production facilities, refineries,
		supply etc. we deal with defensive structures elsewhere.

		So we can say that base X is our main base, and must have certain buildings in it, such as a 
		barracks, starport etc. and say that base Y is our expansion, where we might not want to build
		those things (or maybe we do - but this is all down to strategic preference).

		Templates should be continually re-evaluated, and if written correctly should allow for bases that
		have been destroyed or partially destroyed to be re-constructed.

*/

class BuildOrderTemplate {

public:
//	BuildOrderTemplate(BaseModel* base, Overseer* ov);
	 BuildOrderTemplate(Overseer* ov);
	 void update();
	 void addToOpeningSequence(UnitType unit);
	 	 void addToOpeningSequenceUrgent(UnitType unit);
	 void addToOpeningSequenceWithRally(UnitType unit, int rallyLoc);
	 void addToOpeningSequenceWithRally(UnitType unit, Position rallyLoc);
	 void addToOpeningSequenceWithGuardStrength(UnitType unit, int strength, BuildOrderTemplate* temp );
	 void addToOpeningSequenceWithGuardStrengthAndPosPreference(UnitType unit, int strength, BuildOrderTemplate* temp , bool posPref);
	 void addToOpeningSequence(UpgradeType t);
	 void addToOpeningSequence(TechType t);
	 void addToOpeningSequence(TaskBase* task);
	 void addToOpeningSequence(UnitType unit, int behaviourModelID);
	 void addToOpeningSequence(UnitType unit, BuildOrderTemplate* temp);
	 	 void addToOpeningSequenceUrgent(UnitType unit, BuildOrderTemplate* temp);
	 	 void pushGeneralConstructionTask(UnitType unit);
	 void setBaseModel(BaseModel* b);
	 void setTargetMineralWorkers(int tar);
	 void setTargetGasWorkers(int tar);
	 int getTargetMineralWorkers();
	 int getTargetGasWorkers();
	 BaseModelConsistencyMonitor* getBCM();
	 void manageWorkerRequisitions();
	 void setTargetParent(BaseModel* bm);
	 deque<TaskBase*> getPrimeOrder();
	 bool isManagingWorkerAcquisition();
	 void setManagingWorkerAcquisition(bool s);
private:
	queue<TaskBase*> buildOrder;
	deque<TaskBase*> primeOrder;
	deque<std::pair<int, TaskBase*>> secondaryOrder;
	vector<UnitType> desiredBaseState;
	BaseModel* here;
	Overseer* overseer;
	BaseModelConsistencyMonitor* bcm;
	int targetMineralWorkers;
	int targetGasWorkers;
	BaseModel* targetParent;
	std::map<BaseModel*, std::vector<TilePosition>> pathMap;
	bool managingWorkerAcquisition;

protected:


};