#pragma once

#include "Common.h"
#include "InformationManager.h"
#include "WorkerManager.h"
#include "BuildOrder.h"
#include "BuildOrderQueue.h"

namespace UAlbertaBot
{
typedef std::pair<MacroAct, size_t> MetaPair;
typedef std::vector<MetaPair> MetaPairVector;

struct Strategy
{
    std::string _name;
    BWAPI::Race _race;
	std::string _openingGroup;
    BuildOrder  _buildOrder;

    Strategy()
        : _name("None")
        , _race(BWAPI::Races::None)
 		, _openingGroup("")
    {
    }

	Strategy(const std::string & name, const BWAPI::Race & race, const std::string & openingGroup, const BuildOrder & buildOrder)
        : _name(name)
        , _race(race)
		, _openingGroup(openingGroup)
		, _buildOrder(buildOrder)
	{
    }
};

class The;

class StrategyManager 
{
	StrategyManager();

	The & the;

	BWAPI::Race					    _selfRace;
	BWAPI::Race					    _enemyRace;
    std::map<std::string, Strategy> _strategies;
    int                             _totalGamesPlayed;
    const BuildOrder                _emptyBuildOrder;
	std::string						_openingGroup;
	bool							_hasDropTech;
	int								_highWaterBases;				// most bases we've ever had, terran and protoss only
	bool							_openingStaticDefenseDropped;	// make sure we do this at most once ever

	const	bool				    shouldExpandNow() const;
    const	MetaPairVector		    getProtossBuildOrderGoal();
	const	MetaPairVector		    getTerranBuildOrderGoal();
	const	MetaPairVector		    getZergBuildOrderGoal() const;

	bool							detectSupplyBlock(BuildOrderQueue & queue) const;
	bool							handleExtremeEmergency(BuildOrderQueue & queue);

	bool							canPlanBuildOrderNow() const;
	void							performBuildOrderSearch();

public:
    
	static	StrategyManager &	    Instance();

            void                    addStrategy(const std::string & name, Strategy & strategy);
			void					setOpeningGroup();
	const	std::string &			getOpeningGroup() const;
 	const	MetaPairVector		    getBuildOrderGoal();
	const	BuildOrder &            getOpeningBookBuildOrder() const;

			void					handleUrgentProductionIssues(BuildOrderQueue & queue);
			void					freshProductionPlan();

			bool					dropIsPlanned() const;
			bool					hasDropTech();
};

}