//////////////////////////////////////////////////////////////////////////
//
// This file is part of Iron's source files.
// Iron is free software, licensed under the MIT/X11 License. 
// A copy of the license is provided with the library in the LICENSE file.
// Copyright (c) 2016, Igor Dimitrijevic
//
//////////////////////////////////////////////////////////////////////////


#ifndef HIM_H
#define HIM_H

#include <BWAPI.h>
#include "his.h"
#include <memory>


namespace iron
{

class VBase;



//////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                          //
//                                  class Him
//                                                                                          //
//////////////////////////////////////////////////////////////////////////////////////////////
//

class Him
{
public:
											Him(char) {}

	void									Update();

	const BWAPI::Player						Player() const;
	BWAPI::Player							Player();

	VBase *									StartingBase() const		{ return m_pStartingBase; }

	BWAPI::Race								Race() const				{ return Player()->getRace(); }

	bool									Accessible() const			{ return m_accessible; }
	void									SetNotAccessible()			{ m_accessible = false; }

	bool									StartingBaseDestroyed() const			{ return m_startingBaseDestroyed; }
	void									SetStartingBaseDestroyed()	{ m_startingBaseDestroyed = true; }

	void									AddUnit(BWAPI::Unit u);
	void									AddBuilding(BWAPI::Unit u);
	HisUnit *								FindUnit(BWAPI::Unit u) const;
	HisBuilding *							FindBuilding(BWAPI::Unit u) const;

	void									RemoveUnit(BWAPI::Unit u, bool informOthers);
	void									RemoveBuilding(BWAPI::Unit u, bool informOthers);

	void									OnShowUnit(BWAPI::Unit u);
	void									OnShowBuilding(BWAPI::Unit u);

	void									OnHideUnit(BWAPI::Unit u);
	void									OnHideBuilding(BWAPI::Unit u);
	void									OnDestroyed(BWAPI::Unit u);

	const vector<unique_ptr<HisUnit>> &		Units() const				{ return m_Units; }
	vector<unique_ptr<HisUnit>> &			Units()						{ return m_Units; }

	const map<Unit, HisUnitTrace> &			UnitTrace() const			{ return m_UnitTrace; }

	const vector<unique_ptr<HisBuilding>> &	Buildings() const			{ return m_Buildings; }
	vector<unique_ptr<HisBuilding>> &		Buildings()					{ return m_Buildings; }

	const Area *							GetArea() const;

	void									CheckTanksInFog();

	bool									MayDarkTemplar() const		{ return m_mayDarkTemplar; }
	void									SetMayDarkTemplar()			{ m_mayDarkTemplar = true; }

	bool									MayReaver() const			{ return m_mayReaver; }
	void									SetMayReaver()				{ m_mayReaver = true; }

	bool									MayDragoon() const			{ return m_mayDragoon; }
	void									SetMayDragoon()				{ m_mayDragoon = true; }

	bool									MayWraith() const			{ return m_mayWraith; }
	void									SetMayWraith()				{ m_mayWraith = true; }

	bool									HasCannons() const			{ return m_hasCannons; }
	void									SetHasCannons()				{ m_hasCannons = true; }

	bool									MayHydraOrLurker() const	{ return m_mayHydraOrLurker; }
	void									SetMayHydraOrLurker()		{ m_mayHydraOrLurker = true; }

private:
	void									SetStartingBase(VBase * base)	{ assert_throw(!m_pStartingBase && base); m_pStartingBase = base; }
	void									UpdateStartingBase();
	void									CheckObsoleteInFogUnit(BWAPI::Unit u);
	void									CheckObsoleteInFogBuilding(BWAPI::Unit u);
	void									UpdateUnitTrace();

	vector<unique_ptr<HisUnit>>				m_Units;
	vector<unique_ptr<HisBuilding>>			m_Buildings;
	VBase *									m_pStartingBase = nullptr;
	bool									m_accessible = true;
	bool									m_startingBaseDestroyed = false;
	bool									m_mayDarkTemplar = false;
	bool									m_mayReaver = false;
	bool									m_mayDragoon = false;
	bool									m_mayWraith = false;
	bool									m_hasCannons = false;
	bool									m_mayHydraOrLurker = false;

	map<Unit, HisUnitTrace>					m_UnitTrace;
};


class Him & him();

} // namespace iron


#endif

