//////////////////////////////////////////////////////////////////////////
//
// 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 "enemyScout.h"
#include "../units/him.h"
#include "../units/my.h"
#include "../behavior/defaultBehavior.h"
#include "../behavior/mining.h"
#include "../behavior/exploring.h"
#include "../behavior/constructing.h"
#include "../behavior/fleeing.h"
#include "../behavior/chasing.h"
#include "../Iron.h"

namespace { auto & bw = Broodwar; }




namespace iron
{


//////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                          //
//                                  class EnemyScout
//                                                                                          //
//////////////////////////////////////////////////////////////////////////////////////////////


EnemyScout::EnemyScout()
{
}


EnemyScout::~EnemyScout()
{
//	ReleaseExplorers();
}


string EnemyScout::StateDescription() const
{
	if (!Detected()) return "-";
	if (Detected()) return "detected";

	return "-";
}


void EnemyScout::ReleaseExplorers() const
{
	vector<Exploring *> Explorers = Exploring::Instances();
	for (Exploring * e : Explorers)
		if (e->Agent()->Is(Terran_SCV))
			e->Agent()->ChangeBehavior<DefaultBehavior>(e->Agent());
}


void EnemyScout::OnBWAPIUnitDestroyed(BWAPIUnit * pBWAPIUnit)
{
	if (m_pHisScout == pBWAPIUnit)
		m_pHisScout = nullptr;
}


void EnemyScout::OnFrame_v()
{
	if (me().CompletedUnits(Terran_Marine) >= 1) return Abort();
	if (me().CompletedUnits(Terran_Vulture) >= 1) return Abort();
	
	m_pHisScout = nullptr;
	for (const unique_ptr<HisUnit> & u : him().Units())
		if (u->Type().isWorker())
			if (u->GetArea() == me().GetArea())
				if (groundDist(u->Pos(), me().GetBase(0)->Center()) < 30*32)
					if (!m_pHisScout)
					{
						m_pHisScout = u.get();
					}
					else // this strat only applies to 1 enemy scout.
					{
						m_pHisScout = nullptr;
						break;
					}

	if (m_pHisScout)
	{
		MyUnit * pAttackedSCV = nullptr;
		vector<MyUnit *> ChasingCandidates;

		for (const auto & u : me().Units(Terran_SCV))
			if (u->Completed())
			{
				if (u->Life() < u->PrevLife(10))
					if (findThreatsButWorkers(u.get(), 3*32).empty())
						pAttackedSCV = u.get();

				if (const Mining * m = u->GetBehavior()->IsMining())
					if ((m->State() == Mining::returning) || u->Unit()->isMoving())
						ChasingCandidates.push_back(u.get());

				if (u->GetBehavior()->IsRefining())
					if (u->Unit()->isMoving())
						ChasingCandidates.push_back(u.get());

				if (const Constructing * c = u->GetBehavior()->IsConstructing())
					if (c->State() == Constructing::reachingLocation)
						ChasingCandidates.push_back(u.get());
			}

		if (pAttackedSCV && pAttackedSCV->GetBehavior()->IsConstructing())
		{
			m_maxChasingTime = 1000;
			return pAttackedSCV->ChangeBehavior<Chasing>(pAttackedSCV, m_pHisScout, bool("insist"));
		}

		for (MyUnit * u : ChasingCandidates)
		{
			FaceOff fo(u, m_pHisScout);
			if ((pAttackedSCV == u) ||
				(fo.DistanceToMyRange() < 10) ||
				((fo.DistanceToMyRange() < 40) && pAttackedSCV))
			{
				m_maxChasingTime = 20;
				u->ChangeBehavior<Chasing>(u, m_pHisScout, bool("insist"));
			}
		}

/*
		if (pIntrusiveWorker)
		{
			My<Terran_SCV> * pSCV = findFreeWorker(me().GetVBase(0));
			if (!pSCV)
				if (!Mining::Instances().empty()) pSCV = Mining::Instances().front()->Agent();
				//else if (!Mining::Instances().empty()) pSCV = Mining::Instances().front()->Agent();
			if (pSCV)
				return pSCV->ChangeBehavior<Chasing>(pSCV, pIntrusiveWorker, bool("insist"));
		}
		else
		{
			if (ai()->Frame() - m_lastFrameSawScout > 200)
			{
				ReleaseExplorers();

				m_active = false;
				return;
			}

			if (none_of(Exploring::Instances().begin(), Exploring::Instances().end(),
						[](const Exploring * e) { return e->Agent()->Is(Terran_SCV); }))
				if (My<Terran_SCV> * pWorker = pWorker = findFreeWorker(me().GetVBase(0)))
					pWorker->ChangeBehavior<Exploring>(pWorker, me().GetArea());
		}
*/
	}
}


} // namespace iron



