#pragma once

#include "Common.h"

#include "UnitData.h"
#include "BuildOrderQueue.h"
#include "InformationManager.h"
#include "WorkerManager.h"
#include "BuildManager.h"
#include "ConstructionManager.h"
#include "ScoutManager.h"
#include "StrategyManager.h"

namespace MyBot
{
	class Strategy_CombatTaskManager {

	public:
		bool isAttackEnemyBaseLocationWorkerStarted;


		enum CombatState {
			defenseMode = 0,										// 아군 진지 방어
			gatherToAttack = 1,										// 공격을 위해 아군 기지 근처에 집결
			prepareToAttackStart = 2,								// 공격을 위해 적군 기지 근처에 집결
			attackEnemyChokepoint1 = 3, 								// 적진 길목 1 공격 시작
			attackEnemyChokepoint2 = 4,								// 적진 길목 2 공격 시작
			attackEnemyChokepoint3 = 5,								// 적진 길목 3 공격 시작
			attackEnemyBaseLocation = 6,							// 적진 BaseLocation 공격
			attackMySecondChokepoint,							// 아군 두번째 길목을 공격
			attackEnemySecondChokepoint,						// 적진 두번째 길목을 공격
			attackEnemyFirstExpansionLocation,					// 적진 앞마당을 공격
			attackEnemyMainBaseLocation,						// 적진 본진을 공격
			eliminateEnemy = 99										// 적 Eliminate 
		};

		enum FlyingState {
			moveToSafePosition = 0,									// 대기
			searchForTarget = 1,									// 탐색
			moveToFirstPoint = 2,									// 첫번째 포인트로 이동
			moveToSecondPoint = 3,									// 두번째 포인트로 이동
			moveToThirdPoint = 4,									// 마지막 포인트로 이동
			moveToTarget = 5,										// 공격 목표로 이동
			attackEnemy = 6											// 공격 시작
		};

		CombatState combatState;				/// 지상 전투 상황
		
		FlyingState flyingState;				/// 공중 전투 상황

		BWAPI::Position targetAttackPositionForGroundUnits;
		BWAPI::Position targetAttackPositionForAirUnits;
		BWAPI::Position targetAssemblePositionForGroundUnits;
		BWAPI::Position targetAssemblePositionForAirUnits;

		Strategy_CombatTaskManager() 
		{
			isAttackEnemyBaseLocationWorkerStarted = false;
			combatState = CombatState::defenseMode;

			flyingState = FlyingState::moveToSafePosition;
			concentrationAttackTargetUnit = nullptr;
			mainCombatMutaliskSquadCenterPosition = BWAPI::Positions::None;

			targetAttackPositionForGroundUnits = BWAPI::Positions::None;
			targetAttackPositionForAirUnits = BWAPI::Positions::None;


		};

		/// static singleton 객체를 리턴합니다
		static Strategy_CombatTaskManager &	Instance();

		void update();

		void blockAndHoldOnChokePoint();
		void attackWithLurkerDrop();
		void defensePositionWithHydralisk();

		void burrowAndAmbushAttackWithLurker();

		void attackEnemyWorkerUnitInMainRegion();
		void attackEnemyBuildingUnitInMainRegion();
		void attackEnemyGroundUnitInOurRegion();
		
		void attackEnemyWithMainCombatMutaliskSquad();
		BWAPI::Position mainCombatMutaliskSquadCenterPosition;

		void attackEnemyWithMainCombatGroundSquad();
		void attackEnemyWithEarlyZerglingSquad();

		bool isTimeToStartAttack();
		bool isTimeToRetreatFromCombat();

		
		/// 헬퍼함수 - unit 미션 수행
		void updateUnitMission();
		
		void updateUnitMissionForZerglingAsFindEnemyMainBaseLocation();
		void updateUnitMissionForZerglingAsFastAttack();
		void updateUnitMissionForZerglingAsEliminateAttack();
		void updateUnitMissionForMutaliskAsAttack();
		void updateUnitMissionForOverlord();
		void updateUnitMissionForLurker();
		void updateUnitMissionForQueen();

		void executeEnemyElimination();

		std::map<BWAPI::Unit, BWAPI::Unit> attackerTargetMap;
		BWAPI::Unit concentrationAttackTargetUnit;

		// 헬퍼함수
		int getNumberOfSameTargeting(BWAPI::Unit targetUnit);

		BWAPI::Unit getNearestEnemyWorker(BWAPI::Position from, int radius);

		BWAPI::Unit getNearestEnemyWorkerForMeleeAttack(BWAPI::Position from, int maxSameAttackerCount = 3);

		BWAPI::Position getNearestEnemyUnitToGroundAttack(BWAPI::Position from);

		BWAPI::Unit getNearestAndWeakestEnemyGroundCombatUnit(BWAPI::Position from);

		bool isThereHealthyFriendUnitAround(BWAPI::Position from, int radius);

		BWAPI::Position getFarthestMineralPosition(BWAPI::Position from, BWTA::BaseLocation* baselocation);

		bool isAllMineralExplored(BWTA::BaseLocation* baselocation);

		BWAPI::Unit getEnemyUnitAroundEnemyChokepointClosestToEnemyFirstExpansionLocation();

		BWAPI::Unit getMostUrgentEnemyUnit();

		bool isImpossibleToWinTheCombat();

		bool isEasyToKillEnemyCombatUnitsWithZergling();

		int enemyCombatUnitCount = 0;
		int enemyWorkerUnitCount = 0;
		int enemyZealotCount = 0;
		int enemyMarineCount = 0;
		int enemyZerglingCount = 0;

		int enemyWorkerUnitAroundEnemyBase = 0;
		int enemyWorkerUnitAroundEnemyChokepoint = 0;
		int enemyCombatUnitAroundEnemyBase = 0;
		int enemyCombatUnitAroundEnemyChokepoint = 0;
		int enemyBuildingAroundEnemyBase = 0;
		int enemyBuildingAroundEnemyChokepoint = 0;
		int enemyDefenseBuildingAroundEnemyBase = 0;
		int enemyDefenseBuildingAroundEnemyChokepoint = 0;

		void updateUnitCount();

		BWTA::BaseLocation* getWeakestEnemyBaseLocationForGroundCombatUnit();

		int getMyUnitCount(BWAPI::Position from, int radius);

		BWAPI::Position getAssemblePositionForGroundAttack(BWAPI::Position from, BWAPI::Position to);

		BWTA::BaseLocation* getWeakestEnemyBaseLocationForMutalisk();

		int getDifficultyToAttackWithMutalisk(BWTA::BaseLocation* baseLocation);

		int getAttractionToAttackWithMutalisk(BWTA::BaseLocation* baseLocation);

		BWAPI::Position getTargetPositionInMapToAttackWithMutalisk();

		BWAPI::Position getTargetPositionToAttackWithMutalisk();

		BWAPI::Unit getAttractiveUnitToAttackForMutalisk(BWAPI::Unit mutalisk);

		void moveMutaliskSquad(BWAPI::Position finalTargetPosition, bool isToAttackBaseLocation = false);

		int getAttackPriority(BWAPI::Unit enemyUnit);

		void swarmTest();
	};
}

