#pragma once
#include <BWAPI.h>
#include "BWTA.h"
#include "UnitModel.h"
#include "UnitManager.h"
#include "Synapse.h"
#include <algorithm>
#include <vector>

using namespace BWTA;

class Overseer;
class BaseModelConsistencyMonitor;

class BuildOrderTemplate;

class BaseModel {
public:
	BaseModel(UnitModel* centre, Overseer* ov);
	BaseModel(UnitModel* centre, Overseer* ov, BuildOrderTemplate* bo);

	UnitModel* getSubject();
	void updateBaseModel(vector<UnitModel*> u);
	void drawBaseModel();
	UnitModel* findAvailableWorker();
	set<UnitModel*> getBaseBuildings();
	vector<UnitModel*> getWorkers();
	vector<UnitModel*> getDefenders();
	BaseLocation* getBaseLOC();
	bool hasBuildingComplete(UnitType t);
		bool hasBuildingUnderConstruction(UnitType t);
	bool mineralsExhausted();
		bool gasExhausted();
	void registerNewBuilding(UnitModel* t);
	UnitModel* getBuilding(UnitType t);
	void setBuildOrderTemplate(BuildOrderTemplate* btemp);
	int countNumTypeInBase(UnitType t);
	BaseModelConsistencyMonitor* getBCM();
	void manageWorkerPopulation();
	set<Unit*> getBaseGeysers();
	set<Unit*> getBaseMinerals();
	int getCurMineralsLeft();
	int getStartMinerals();
	Position getBaseAttackLoc();
		Position getBaseThreatLoc();
	Unit* returnRandomMinPatch();
		UnitModel* returnRandomPylon();
	bool isBeingDefended();
	void manageLocalDefenders();
	std::vector<UnitModel*> getBaseDefenders();
	void setMainBase();
	bool isMainBase();
	bool isFriendlyBase();
	bool isUnderAttack();
	bool isUnderThreat();
		bool isUnderThreatMin(int num);
	Position getPosition();
	bool isAlive();
	bool setAlive();
	BuildOrderTemplate* getBuildOrder();
	bool hasSpawnedExpansion();
	void setSpawned(bool s);
	BWTA::Region* getBaseRegion();
	int mineralValue();
	int getNumMineralWorkers();
	int getNumGasWorkers();
	void randomAssignMineralWorker();
	void setWorkerManagement(bool status);
	BaseModel* getParent();
	void setParent(BaseModel* p);
	void monitorForPower();
	void setSubject(UnitModel* um);
	void setMainBaseExpandTimer(int t);
	void setExpandSubject(ExpandTask* e);
	UnitModel* getRandomBuilding();
	void registerWorker(UnitModel* um);
	void deRegisterWorker(UnitModel* um);
private:
	UnitModel* subject;
	vector<UnitModel*> activeWorkers;
	vector<UnitModel*> defenders;
	int workersMiningMinerals;
	int workersGatheringGas;
	bool managingWorkers;
	set<UnitModel*> baseContents;
	BuildOrderTemplate* baseTemplate;
	Overseer* overseer;
	set<Unit*> baseMinerals;
	set<Unit*> baseGeysers;
	BaseModel* parent;
	ExpandTask* expandSubject;
	int workerClaimTimer;

	bool main;
	bool alive;
	bool friendly;
	Position pos;
	Position threatLoc;
	bool respawned;

	int startMinerals;
	int startGas;
	int curMinerals;
	int curGas;
	int buildFrame;

	bool spawnedExpansion;
	BWTA::BaseLocation* loc;
	BWTA::Region* baseRegion;

	int mainBaseSpawnCounter;
	int mainBaseSpawnTimer;

protected:


};