#pragma once
#include <BWAPI.h>
#include <windows.h>
#include "Common.h"
#include "SquadAgent.h"
#include "InformationManager.h"

typedef std::set<SquadAgent*> SquadSet;
typedef std::map<BWAPI::Unit*, SquadAgent*> UnitToSquadMap;
typedef std::set< std::pair<SquadAgent*, SquadAgent*> > UnitPairSet;

class SquadManager
{
public:
	SquadManager();
	void newSquad(const UnitSet &units);
	SquadAgent* testSquad(const UnitSet &units);
	void newSquad(BWAPI::Unit* unit);
	void unitTraining(BWAPI::Unit* unit);
	void newBunkerSquad(BWAPI::Unit* unit);
	void newScoutSquad(BWAPI::Unit* unit);
	void newDetectorSquad(BWAPI::Unit* unit);
	void onFrame();
//	void orderGetPosition(BWAPI::Position positionTarget);
	void onUnitDestroy(BWAPI::Unit* unit);
	int getUnitFrameCreated(BWAPI::Unit* unit);
	void newEnemy(BWAPI::Unit* enemy);
	void newEnemy(BWAPI::Unit* enemy, SquadAgent* oldSquad);
	void onEnemyEvade(BWAPI::Unit* enemy);
	void onEnemyDestroy(BWAPI::Unit* enemy);

	void requestRetreat(SquadAgent* squad);
	BWAPI::Position getBestTarget();
	BWAPI::Position getScoutTarget();
	void removeMergingSquads(SquadAgent *squad);
	int normalSquads();

	SquadAgent* getClosestSquad(BWAPI::Position toPosition, SquadAgent* ignoreSquad, bool ignoreNoMergeable = false, bool ignoreNoAssignable = false);

	UnitSet _unitsTraning;
	SquadAgent* _creatingSquad;
	SquadAgent* _leadSquad;
	SquadAgent* _searchSquad;
	SquadAgent* _detectorSquad;
	SquadSet _squads;
	UnitToSquadMap _unitToSquadMap;
	UnitToSquadMap _enemyToSquadMap;
 	BWAPI::Position _positionTarget;
	UnitPairSet _squadsToMerge;

private:
	log4cxx::LoggerPtr _logger;

	//SquadAgent* getClosestSquad(BWAPI::Position toPosition, SquadAgent* ignoreSquad);
	void checkAutoMerge();
	void checkMerge();
    void checkHighLevelOrder();
	void mergeUnitsAndEnemies(SquadAgent* squad1, SquadAgent* squad2);
	static bool compare( std::pair<BWAPI::Position, int> i, std::pair<BWAPI::Position, int> j);
	SquadAgent* getBestSquadLead();
	bool isSpecialSquad(SquadAgent* squad);
	bool isSquadNoMergeable(SquadAgent* squad);
	bool isSquadNoEnemyAssignable(SquadAgent* squad);

};