#include "StrategyManager.h"

using namespace MyBot;


void StrategyManager::updateCombatTask()
{
	BWAPI::Unit targetEnemyUnit = nullptr;
	BWAPI::Position targetEnemyUnitPosition = BWAPI::Positions::None;

	if (BWAPI::Broodwar->self()->getRace() == BWAPI::Races::Zerg) {

		// 아군 전략에 따른 공격 타스크
		if (true) {

			if (enemyMainBaseLocation != nullptr) {

				// Zerg_Combat_4Drone_Zergling_Rush 의 경우, 상황을 고려하지 않고 무조건 공격
				if (myCurrentCombatStrategy == CombatStrategy::Zerg_Combat_4Drone_Zergling_Rush) {
					insertTask(StrategicTask(TaskGoalType::Attack_Enemy_BaseLocation_With_Early_Zergling_Unit, BWAPI::UnitTypes::None, BWAPI::TechTypes::None, BWAPI::UpgradeTypes::None, nullptr, BWAPI::Positions::None, 0));
				}
				else {
					insertTask(StrategicTask(TaskGoalType::Attack_Enemy_BaseLocation_With_Mutalisk, BWAPI::UnitTypes::None, BWAPI::TechTypes::None, BWAPI::UpgradeTypes::None, nullptr, BWAPI::Positions::None, 0));
					insertTask(StrategicTask(TaskGoalType::Attack_Enemy_BaseLocation_With_Ground_Unit, BWAPI::UnitTypes::None, BWAPI::TechTypes::None, BWAPI::UpgradeTypes::None, nullptr, BWAPI::Positions::None, 0));
				}
			}
		}

		// 아군 상황에 따른 공격 타스크
		if (true) {

			// 매복 러커 : 상대방에게 하이템플러, 리버, 옵저버, 시즈탱크, 사이언스베슬, 뮤탈리스크 가 나오기 전까지 사용
			// 대 프로토스 : 입구 봉쇄. 히드라/저글링과 함께
			// 대 테란 메카닉 : 입구 봉쇄. 히드라/저글링과 함께
			// 대 테란 바이오닉 : 마린 / 메딕 스탑러커
			// 대 저그 : 입구 봉쇄. 히드라/저글링과 함께
			if (isToBurrowAndAmbushAttackWithLurker) {
				if (InformationManager::Instance().getUnitData(StrategyManager::Instance().enemyPlayer).getNumCreatedUnits(BWAPI::UnitTypes::Protoss_High_Templar) > 6
					|| InformationManager::Instance().getUnitData(StrategyManager::Instance().enemyPlayer).getNumCreatedUnits(BWAPI::UnitTypes::Protoss_Archon) > 6
					|| InformationManager::Instance().getUnitData(StrategyManager::Instance().enemyPlayer).getNumCreatedUnits(BWAPI::UnitTypes::Protoss_Dark_Archon) > 6
					|| InformationManager::Instance().getUnitData(StrategyManager::Instance().enemyPlayer).getNumCreatedUnits(BWAPI::UnitTypes::Protoss_Observer) > 6
					|| InformationManager::Instance().getUnitData(StrategyManager::Instance().enemyPlayer).getNumCreatedUnits(BWAPI::UnitTypes::Protoss_Reaver) > 6
					|| InformationManager::Instance().getUnitData(StrategyManager::Instance().enemyPlayer).getNumCreatedUnits(BWAPI::UnitTypes::Protoss_Carrier) > 6
					|| InformationManager::Instance().getUnitData(StrategyManager::Instance().enemyPlayer).getNumCreatedUnits(BWAPI::UnitTypes::Protoss_Arbiter) > 6
					|| InformationManager::Instance().getUnitData(StrategyManager::Instance().enemyPlayer).getNumCreatedUnits(BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode) > 8
					|| InformationManager::Instance().getUnitData(StrategyManager::Instance().enemyPlayer).getNumCreatedUnits(BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode) > 8
					|| InformationManager::Instance().getUnitData(StrategyManager::Instance().enemyPlayer).getNumCreatedUnits(BWAPI::UnitTypes::Terran_Science_Vessel) > 6
					|| InformationManager::Instance().getUnitData(StrategyManager::Instance().enemyPlayer).getNumCreatedUnits(BWAPI::UnitTypes::Zerg_Mutalisk) > 8
					|| InformationManager::Instance().getUnitData(StrategyManager::Instance().enemyPlayer).getNumCreatedUnits(BWAPI::UnitTypes::Zerg_Guardian) > 8
				) {
					isToBurrowAndAmbushAttackWithLurker = false;
					breakUpSquad(&ambushCombatLurkerSquad);
				}
			}

			if (isToBurrowAndAmbushAttackWithLurker) {
				if (BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Lurker) >= 4)
				{
					insertTask(StrategicTask(TaskGoalType::Burrow_And_Ambush_Attack_With_Lurker, BWAPI::UnitTypes::None, BWAPI::TechTypes::None, BWAPI::UpgradeTypes::None, nullptr, BWAPI::Positions::None, 0));
				}
			}

			if (BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Sunken_Colony) < 3) {

				if (InformationManager::Instance().getNumUnits(BWAPI::UnitTypes::Terran_Vulture, InformationManager::Instance().enemyPlayer) >= 3
					|| InformationManager::Instance().getNumUnits(BWAPI::UnitTypes::Zerg_Zergling, InformationManager::Instance().enemyPlayer) >= 6
					|| InformationManager::Instance().getNumUnits(BWAPI::UnitTypes::Protoss_Zealot, InformationManager::Instance().enemyPlayer) >= 4)
				{
					insertTask(StrategicTask(TaskGoalType::Block_And_Hold_On_ChokePoint, BWAPI::UnitTypes::None, BWAPI::TechTypes::None, BWAPI::UpgradeTypes::None, nullptr, BWAPI::Positions::None, 0));
				}
			}

		}

		// 적군 종족, 적군 전략 및 아군 전략에 따른 공격 타스크
		if (InformationManager::Instance().enemyRace == BWAPI::Races::Protoss)
		{
			// 적군이 성큰 / 벙커 / 캐논 러시 전략이면, 전면 공격 안함

		}
		else if (InformationManager::Instance().enemyRace == BWAPI::Races::Terran)
		{
		}
		else if (InformationManager::Instance().enemyRace == BWAPI::Races::Zerg)
		{

		}

		// 특정 적군 유닛 발견에 따른 공격 타스크
		if (true) {

			// 수송선 발견시
			if (enemyUnitData->getNumUnits(BWAPI::UnitTypes::Protoss_Shuttle) > 0
				|| enemyUnitData->getNumUnits(BWAPI::UnitTypes::Terran_Dropship) > 0)
			{
			}

			// 아군 본진에 들어온 적 일꾼 유닛 발견시
			for (auto & it : InformationManager::Instance().getUnitAndUnitInfoMap(InformationManager::Instance().enemyPlayer)) {
				BWAPI::Unit enemyUnit = it.first;
				UnitInfo & enemyUnitInfo = it.second;

				if (BWTA::getRegion(enemyUnitInfo.lastPosition) == myMainBaseLocation->getRegion()
					|| BWTA::getRegion(enemyUnitInfo.lastPosition) == myFirstExpansionBaseLocation->getRegion())
				{
					if (enemyUnitInfo.lastHealth > 0 && enemyUnitInfo.isLastPositionValid == true)
					{
						if (enemyUnitInfo.type.isWorker()) {
							insertTask(StrategicTask(TaskGoalType::Attack_Enemy_Worker_In_Main_Region));
							break;
						}
					}
				}
			}
			// 아군 본진에 들어온 적 건물 유닛 발견시
			for (auto & it : InformationManager::Instance().getUnitAndUnitInfoMap(InformationManager::Instance().enemyPlayer)) {
				BWAPI::Unit enemyUnit = it.first;
				UnitInfo & enemyUnitInfo = it.second;

				if (BWTA::getRegion(enemyUnitInfo.lastPosition) == myMainBaseLocation->getRegion()
					|| BWTA::getRegion(enemyUnitInfo.lastPosition) == myFirstExpansionBaseLocation->getRegion())
				{
					if (enemyUnitInfo.lastHealth > 0 && enemyUnitInfo.isLastPositionValid == true)
					{
						if (enemyUnitInfo.type.isBuilding()) {
							if (enemyUnitInfo.type == BWAPI::UnitTypes::Terran_Bunker
								|| enemyUnitInfo.type == BWAPI::UnitTypes::Terran_Refinery
								|| enemyUnitInfo.type == BWAPI::UnitTypes::Protoss_Pylon
								|| enemyUnitInfo.type == BWAPI::UnitTypes::Protoss_Photon_Cannon
								|| enemyUnitInfo.type == BWAPI::UnitTypes::Protoss_Assimilator
								|| enemyUnitInfo.type == BWAPI::UnitTypes::Zerg_Extractor
								|| enemyUnitInfo.type == BWAPI::UnitTypes::Zerg_Creep_Colony
								|| enemyUnitInfo.type == BWAPI::UnitTypes::Zerg_Nydus_Canal
								|| enemyUnitInfo.type == BWAPI::UnitTypes::Zerg_Sunken_Colony)
							{
								insertTask(StrategicTask(TaskGoalType::Attack_Enemy_Dangerous_Building_In_Main_Region));
								break;
							}
						}
					}
				}
			}

			// 아군 본진에 들어온 적 지상유닛 발견시
			for (auto & it : InformationManager::Instance().getUnitAndUnitInfoMap(InformationManager::Instance().enemyPlayer)) {
				BWAPI::Unit enemyUnit = it.first;
				UnitInfo & enemyUnitInfo = it.second;

				if (enemyUnitInfo.type.isWorker() == false
					&& enemyUnitInfo.type.canAttack()
					&& enemyUnitInfo.type.isFlyer() == false
					&& enemyUnitInfo.lastHealth > 0
					&& enemyUnitInfo.isLastPositionValid == true) 
				{
					for (BWTA::BaseLocation* baselocation : InformationManager::Instance().getOccupiedBaseLocations(InformationManager::Instance().selfPlayer)) {
						if (baselocation->getPosition().getDistance(enemyUnitInfo.lastPosition) < 16 * TILE_SIZE) {
							insertTask(StrategicTask(TaskGoalType::Attack_Enemy_Ground_Unit_In_Our_Region));
							break;
						}
					}
				}
			}

			// 하이템플러, 다크아칸, 디파일러 발견시

			// 적군이 성큰 / 벙커 / 캐논 러시 전략이면, 방어 성큰 건설 및 드론 동원해서 대응

			// 멀티 발견시

		}
				
		// 거의 승리한 상황 - 적군 ResourceDepot 모두 파괴시 Eliminate 시키기 
		if (BWAPI::Broodwar->getFrameCount() > 24 * 60 * 5) {

			int myBuildingCount = 0;
			int myNonBuildingCount = 0;

			int enemyBuildingCount = 0;
			int enemyNonBuildingCount = 0;
			for (auto & it : InformationManager::Instance().getUnitAndUnitInfoMap(InformationManager::Instance().enemyPlayer)) {
				BWAPI::Unit enemyUnit = it.first;
				UnitInfo & enemyUnitInfo = it.second;

				if (enemyUnitInfo.type.isBuilding()) {
					enemyBuildingCount++;
				}
				else {
					enemyNonBuildingCount++;
				}
			}
			for (auto & it : InformationManager::Instance().getUnitAndUnitInfoMap(InformationManager::Instance().selfPlayer)) {
				BWAPI::Unit myUnit = it.first;
				UnitInfo & myUnitInfo = it.second;

				if (myUnitInfo.type.isBuilding()) {
					myBuildingCount++;
				}
				else {
					myNonBuildingCount++;
				}
			}

			// 적군 유닛을 많이 죽였고, 아군 서플라이가 50 을 넘었으면
			if (selfPlayer->supplyUsed() > 50 * 2) {

				// 적군 본진에 아군 유닛이 20 이상 도착했으면 거의 게임 끝난 것
				int myUnitCountAroundEnemyMainBaseLocation = 0;
				for (BWAPI::Unit unit : BWAPI::Broodwar->getUnitsInRadius(enemyMainBaseLocation->getPosition(), 8 * TILE_SIZE)) {
					if (unit->getPlayer() == selfPlayer) {
						myUnitCountAroundEnemyMainBaseLocation++;
					}
				}
				if (myUnitCountAroundEnemyMainBaseLocation > 20) {

					isToBurrowOnEmptyBaseLocation = false;
					isToBurrowAndAmbushAttackWithLurker = false;

					eraseTask(StrategicTask(TaskGoalType::Burrow_On_Empty_BaseLocation));
					eraseTask(StrategicTask(TaskGoalType::Burrow_And_Ambush_Attack_With_Lurker));

					insertTask(StrategicTask(TaskGoalType::Eliminate_Enemy_Player));
				}
			}
		}


	}
}

bool StrategyManager::isGoodTimingToStartGroundAttack()
{
	bool result = false;

	if (BWAPI::Broodwar->self()->getRace() == BWAPI::Races::Zerg) {

		// 아군 빌드 전략 및 전투 전략에 따라,  아군 유닛 / 리서치 / 업그레이드 상황에 따라 판단
		if (myCurrentCombatStrategy == CombatStrategy::Zerg_Combat_4Drone_Zergling_Rush) {

			result = true;

		}
		else if (myCurrentCombatStrategy == CombatStrategy::Zerg_Combat_Front_Defense_Mutalisk_BackRush) {

			if (myCurrentBuildStrategy == BuildStrategy::Zerg_Build_Zergling_Lurker_Mutalisk) {
				if (BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Zergling) >= 24
					&& BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Lurker) >= 4
					&& BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Mutalisk) >= 12
				){
					result = true;
				}
			}
		}
		else if (myCurrentCombatStrategy == CombatStrategy::Zerg_Combat_Front_Ground_Rush) {
			if (myCurrentBuildStrategy == BuildStrategy::Zerg_Build_Zergling_Only) {
				if (BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Zergling) >= 12
					){
					result = true;
				}
			}
			else if (myCurrentBuildStrategy == BuildStrategy::Zerg_Build_Zergling_Hydralisk)
			{
				if (BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Zergling) >= 20
					&& BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Hydralisk) >= 12
					){
					result = true;
				}
			}
			else if (myCurrentBuildStrategy == BuildStrategy::Zerg_Build_Zergling_Hydralisk_Defiler)
			{
				if (BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Zergling) >= 20
					&& BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Hydralisk) >= 24
					&& BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Defiler) >= 2
					&& BWAPI::Broodwar->self()->hasResearched(BWAPI::TechTypes::Consume) == true
					){
					result = true;
				}
			}
			else if (myCurrentBuildStrategy == BuildStrategy::Zerg_Build_Zergling_Hydralisk_Lurker)
			{
				if (BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Zergling) >= 20
					&& BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Hydralisk) >= 24
					&& BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Lurker) >= 8
				){
					result = true;
				}
			}
			else if (myCurrentBuildStrategy == BuildStrategy::Zerg_Build_Zergling_Hydralisk_Lurker_Defiler)
			{
				if (BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Zergling) >= 20
					&& BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Hydralisk) >= 24
					&& BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Lurker) >= 8
					&& BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Defiler) >= 2
					&& BWAPI::Broodwar->self()->hasResearched(BWAPI::TechTypes::Consume) == true
				){
					result = true;
				}
			}
			else if (myCurrentBuildStrategy == BuildStrategy::Zerg_Build_Zergling_Lurker_Defiler) {
				if (BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Zergling) >= 20
					&& BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Lurker) >= 8
					&& BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Defiler) >= 2
					&& BWAPI::Broodwar->self()->hasResearched(BWAPI::TechTypes::Consume) == true
					){
					result = true;
				}
			}
			else if (myCurrentBuildStrategy == BuildStrategy::Zerg_Build_Zergling_Lurker_Mutalisk) {
				if (BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Zergling) >= 20
					&& BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Lurker) >= 4
					&& BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Mutalisk) >= 12
				){
					result = true;
				}
			}
			else if (myCurrentBuildStrategy == BuildStrategy::Zerg_Build_Air_Focused) {
				if (BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Zergling) >= 24
					&& BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Mutalisk) >= 20
					&& BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Scourge) >= 8
				){
					result = true;
				}
			}
			else if (myCurrentBuildStrategy == BuildStrategy::Zerg_Build_Zergling_Lurker_Mutalisk) {
				if (BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Zergling) >= 24
					&& BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Lurker) >= 4
					&& BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Mutalisk) >= 8
				){
					result = true;
				}
			}
		}
	}

	return result;
}

bool StrategyManager::isGoodTimingToStartAirAttack()
{
	bool result = false;

	if (BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Zerg_Mutalisk) >= 16
		){
		result = true;
	}

	return result;
}
