//////////////////////////////////////////////////////////////////////////
//
// 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
//
//////////////////////////////////////////////////////////////////////////


#include "turret.h"
#include "../strategy/strategy.h"
#include "../strategy/freeTurrets.h"
#include "../Iron.h"

namespace { auto & bw = Broodwar; }


namespace iron
{


//////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                          //
//                                  class My<Terran_Missile_Turret>
//                                                                                          //
//////////////////////////////////////////////////////////////////////////////////////////////


template<>
class ExpertInConstructing<Terran_Missile_Turret> : public ConstructingExpert
{
public:
						ExpertInConstructing() : ConstructingExpert(Terran_Missile_Turret) {}

	void				UpdateConstructingPriority() override;

private:
};


void ExpertInConstructing<Terran_Missile_Turret>::UpdateConstructingPriority()
{
	m_priority = 0;

	if (me().CompletedBuildings(Terran_Engineering_Bay) == 0) { m_priority = 0; return; }

	if (me().FindBuildingNeedingBuilder(Type()))
	{
		m_priority = 299;
		return;
	}

	{
		int maxPriority = 0;
		VBase * pUrgentBase = nullptr;

		for (VBase * base : me().Bases())
		{
			int priority = 0;

			int turretsInBase = count_if(me().Buildings(Terran_Missile_Turret).begin(), me().Buildings(Terran_Missile_Turret).end(),
				[base](const unique_ptr<MyBuilding> & b) { return b->GetStronghold() == base->GetStronghold(); });

			if ((turretsInBase == 0) && (me().Bases().size() >= 2))
				priority = 460; // greater than CC's priority
			else
			{
				if (turretsInBase < 5)
				{
					priority = 300 - turretsInBase*40;
				}

				if (auto * pFreeTurrets = ai()->GetStrategy()->Active<FreeTurrets>())
					if (pFreeTurrets->NeedManyTurrets() || pFreeTurrets->NeedManyManyTurrets())
						if (turretsInBase < (pFreeTurrets->NeedManyManyTurrets() ? 10 : 8))
						{
//							priority = 400 - turretsInBase*(pFreeTurrets->NeedManyManyTurrets() ? 15 : 20);
							priority = (pFreeTurrets->NeedManyManyTurrets() ? 550 : 460) - turretsInBase*40;
						}
			}

			if (priority > maxPriority)
			{
				maxPriority = priority;
				pUrgentBase = base;
			}
		}

		if (pUrgentBase)
		{
			m_priority = maxPriority;
			SetBase(pUrgentBase);
			return;
		}
	}
}


ExpertInConstructing<Terran_Missile_Turret>	My<Terran_Missile_Turret>::m_ConstructingExpert;

ConstructingExpert * My<Terran_Missile_Turret>::GetConstructingExpert() { return &m_ConstructingExpert; }


template<>
class ExpertInConstructingFree<Terran_Missile_Turret> : public ConstructingExpert
{
public:
						ExpertInConstructingFree() : ConstructingExpert(Terran_Missile_Turret) {}

	void				UpdateConstructingPriority() override;

private:
	bool				Free() const override					{ return true; }
	TilePosition		GetFreeLocation() const override;
	My<Terran_SCV> *	GetFreeBuilder() const override;
};


TilePosition ExpertInConstructingFree<Terran_Missile_Turret>::GetFreeLocation() const
{
	if (auto * pFreeTurrets = ai()->GetStrategy()->Active<FreeTurrets>())
		return pFreeTurrets->NextLocation();

	return TilePositions::None;
}


My<Terran_SCV> * ExpertInConstructingFree<Terran_Missile_Turret>::GetFreeBuilder() const
{
	if (auto * pFreeTurrets = ai()->GetStrategy()->Active<FreeTurrets>())
		return pFreeTurrets->Builder();

	return nullptr;
}


void ExpertInConstructingFree<Terran_Missile_Turret>::UpdateConstructingPriority()
{
	m_priority = 0;

	if (me().CompletedBuildings(Terran_Engineering_Bay) == 0) return;

	if (auto * pFreeTurrets = ai()->GetStrategy()->Active<FreeTurrets>())
		if (pFreeTurrets->NextLocation() != TilePositions::None)
			if (pFreeTurrets->Priority() > 0)
			{
				m_priority = pFreeTurrets->Priority();
				return;
			}
}


ExpertInConstructingFree<Terran_Missile_Turret>	My<Terran_Missile_Turret>::m_ConstructingFreeExpert;

ConstructingExpert * My<Terran_Missile_Turret>::GetConstructingFreeExpert() { return &m_ConstructingFreeExpert; }


My<Terran_Missile_Turret>::My(BWAPI::Unit u)
	: MyBuilding(u, make_unique<DefaultBehavior>(this))
{
	assert_throw(u->getType() == Terran_Missile_Turret);
	assert_throw(m_ConstructingExpert.Unselected() || m_ConstructingFreeExpert.Unselected());

	m_ConstructingExpert.OnBuildingCreated();
	m_ConstructingFreeExpert.OnBuildingCreated();
	
}


void My<Terran_Missile_Turret>::DefaultBehaviorOnFrame()
{CI(this);
	if (DefaultBehaviorOnFrame_common()) return;
}




	
} // namespace iron



