#pragma once
#include "InformationManager.h"

#define WORKERS_PER_MINERAL 2

typedef std::map<BWAPI::Unit*, int> ResourceToWorkerMap;
typedef std::map<BWAPI::Unit*, BWAPI::Unit*> WorkerToTargetMap;
typedef std::map<BWAPI::Unit*, std::pair<BWAPI::TilePosition, BWAPI::UnitType> > WorkerToBuildOrderMap;
typedef std::map<BWAPI::Unit*, BWAPI::Unit*> WorkerToTargetMap;
typedef std::map<BWAPI::Unit*, BWTA::BaseLocation*> WorkerToBaseMap;

class WorkerManager
{
public:
	enum State
	{
		Gathering_Mineral,
		Gathering_Gas,
		Building,
		Defending,
		Attacking,
		Bunker_Support
	};
	WorkerManager();
	void addUnit(BWAPI::Unit* unit);
	void onUnitDestroy(BWAPI::Unit* unit);
	void onMineralDestroy(BWAPI::Unit* mineralField);
	void onFrame();
	bool needWorkers();
	BWAPI::Unit* getWorkerForTask(BWAPI::Position toPosition);
	int getBuildingWorkers();
	void workerBuildingRefinery();
	bool isUnderConstruction(BWAPI::UnitType type);
	void buildRequest(BWAPI::TilePosition locationToBuild, BWAPI::UnitType buildType);
	bool workersDefending();
	bool workersDefending(BWAPI::Unit* target);
	unsigned int getWorkersMining();
	void defenseBase(BWAPI::Unit* unit);
	void rebalanceGathering(); // TODO
	void reassignRevomedMinerals();
	void supportWorker();
	int workersSupporting();
	void supportWorkerDone();

	UnitSet _workerUnits;
	WorkerToTargetMap _workersTarget;
	ResourceToWorkerMap _mineralsExploitation;
	ResourceToWorkerMap _gasExploitation;
	std::map<BWAPI::Unit*, WorkerManager::State> _workerState;
	WorkerToBuildOrderMap _workerBuildOrder;

private:
	log4cxx::LoggerPtr _logger;

	BWAPI::Unit* getBestMineral();
	void tryMiningTrick(BWAPI::Unit* worker);

	int _lastFrameCount;
	int _accumluatedMinerals[61];	// We save the "accumulated minerals" for the last 60 seconds (initially, it's all 50s, since you start with 50 minerals)
	int _mineralPS, _mineralPM;
	double _averageMineralPS, _averageMineralPM;
	UnitSet _workerBuildingRefinery;
	UnitToTimeMap _workerStartBuilding;
	UnitToTimeMap _workerStartAttacking;
};