using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LDGrowthManager : MonoBehaviour
{
    private MapGrid theMap;
    private GameManager theGame;

    public GameObject Prefab_ChangingPoof;

    public int iGrowthScore;
    public AudioClip clip_NewLandmark;

    [Header("Water Spawner")]
    public GameObject Prefab_WaterSpawner;
    public float TimeBetweenCheckWaterSpawners;
    public int GrowthScoreRequiredToMakeWaterSpawners;

    [Header("HealthTree Spawner")]
    public GameObject Prefab_TreeSpawner;
    public float TimeBetweenCheckTreeSpawners;
    public int GrowthScoreRequiredToMakeTreeSpawners;


    [Header("DefenseTower Spawner")]
    public GameObject Prefab_DefenseTower;
    public float TimeBetweenCheckDefenseTower;
    public int GrowthScoreRequiredToMakeDefenseTower;

    [Header("CollectionTower Spawner")]
    public GameObject Prefab_CollectionTower;
    public float TimeBetweenCheckCollectionTower;
    public int GrowthScoreRequiredToMakeCollectionTower;

	// Use this for initialization
	void Start () 
    {
		theGame = GameManager.GetGame();
        theMap = theGame.theWorld;
    }
	
	// Update is called once per frame
	void Update () 
    {

	}

    public void OnNewGame()
    {
        StopAllCoroutines();
        iGrowthScore = 0;

        theGame = GameManager.GetGame();
        StartCoroutine(Coroutine_CheckPlaceEggs());
        StartCoroutine(Coroutine_CheckPlaceTrees());
        StartCoroutine(Coroutine_CheckPlaceDefenseTower());
        StartCoroutine(Coroutine_CheckPlaceCollectionTower());
    }

    IEnumerator Coroutine_CheckPlaceTrees()
    {
        float fCheckTimer = TimeBetweenCheckTreeSpawners * 2.0f;
        while (true)
        {
            if (theGame.GetGameState() != EGameState.gameplay)
            {
                yield return null;
                continue;
            }

            fCheckTimer -= Time.deltaTime;
            if (fCheckTimer < 0f && iGrowthScore >= GrowthScoreRequiredToMakeTreeSpawners)
            {
                if (TryToPlaceTreeSpawner())
                {
                    fCheckTimer = TimeBetweenCheckTreeSpawners;
                }
                else
                {
                    fCheckTimer = 3.0f;
                }
            }
            yield return null;
        }
    }

    IEnumerator Coroutine_CheckPlaceEggs()
    {
        float fCheckTimer = TimeBetweenCheckWaterSpawners * 2.0f;
        while (true)
        {
            if (theGame.GetGameState() != EGameState.gameplay)
            {
                yield return null;
                continue;
            }
            fCheckTimer -= Time.deltaTime;
            if (fCheckTimer < 0f && iGrowthScore >= GrowthScoreRequiredToMakeWaterSpawners)
            {
                if (TryToPlaceWaterSpawner())
                {
                    fCheckTimer = TimeBetweenCheckWaterSpawners;
                }
                else
                {
                    fCheckTimer += 3.0f;
                }
            }
            yield return null;
        }
    }

    IEnumerator Coroutine_CheckPlaceDefenseTower()
    {
        float fCheckTimer = TimeBetweenCheckDefenseTower * 2.0f;
        while (true)
        {
            if (theGame.GetGameState() != EGameState.gameplay)
            {
                yield return null;
                continue;
            }
            fCheckTimer -= Time.deltaTime;
            if (fCheckTimer < 0f && iGrowthScore >= TimeBetweenCheckDefenseTower)
            {
                if (TryToPlaceDefenseTower())
                {
                    fCheckTimer = TimeBetweenCheckDefenseTower;
                }
                else
                {
                    fCheckTimer += 3.0f;
                }
            }
            yield return null;
        }
    }

    IEnumerator Coroutine_CheckPlaceCollectionTower()
    {
        float fCheckTimer = TimeBetweenCheckCollectionTower * 2.0f;
        while (true)
        {
            if (theGame.GetGameState() != EGameState.gameplay)
            {
                yield return null;
                continue;
            }
            fCheckTimer -= Time.deltaTime;
            if (fCheckTimer < 0f && iGrowthScore >= TimeBetweenCheckCollectionTower)
            {
                if (TryToPlaceCollectionTower())
                {
                    fCheckTimer = TimeBetweenCheckCollectionTower;
                }
                else
                {
                    fCheckTimer += 3.0f;
                }
            }
            yield return null;
        }
    }

    bool TryToPlaceTreeSpawner()
    {
        int iGoodTreeIndex = GetTileIndexSuitableFor(ETerrainType.grass, 1);
        if (iGoodTreeIndex != -1)
        {
            Vector2 vGamePos = theMap.GetVectorForTile(iGoodTreeIndex);

            vGamePos.x += 0.5f;
            vGamePos.y += 0.5f;

            theGame.PlayParticleEffect(vGamePos, Prefab_ChangingPoof);
            LDGameActor newSpawner = theGame.SpawnActorPrefab(vGamePos, Prefab_TreeSpawner);
            theGame.theAIManager.RegisterLandmark(newSpawner);
            TM_AudioManager.PlayClip(clip_NewLandmark);
            return true;
        }

        Debug.Log("Couldn't do it, i'm bad.");
        return false;
    }

    bool TryToPlaceDefenseTower()
    {
        int iGoodTreeIndex = GetTileIndexSuitableFor(ETerrainType.grass, 1);
        if (iGoodTreeIndex != -1)
        {
            Vector2 vGamePos = theMap.GetVectorForTile(iGoodTreeIndex);

            vGamePos.x += 0.5f;
            vGamePos.y += 0.5f;

            theGame.PlayParticleEffect(vGamePos, Prefab_ChangingPoof);
            LDGameActor newSpawner = theGame.SpawnActorPrefab(vGamePos, Prefab_DefenseTower);
            theGame.theAIManager.RegisterLandmark(newSpawner);
            TM_AudioManager.PlayClip(clip_NewLandmark);
            return true;
        }

        Debug.Log("Couldn't do it, i'm bad.");
        return false;
    }


    bool TryToPlaceCollectionTower()
    {
        int iGoodTreeIndex = GetTileIndexSuitableFor(ETerrainType.grass, 1);
        if (iGoodTreeIndex != -1)
        {
            Vector2 vGamePos = theMap.GetVectorForTile(iGoodTreeIndex);

            vGamePos.x += 0.5f;
            vGamePos.y += 0.5f;

            theGame.PlayParticleEffect(vGamePos, Prefab_ChangingPoof);
            LDGameActor newSpawner = theGame.SpawnActorPrefab(vGamePos, Prefab_CollectionTower);
            theGame.theAIManager.RegisterLandmark(newSpawner);
            TM_AudioManager.PlayClip(clip_NewLandmark);
            return true;
        }

        Debug.Log("Couldn't do it, i'm bad.");
        return false;
    }

    bool TryToPlaceWaterSpawner()
    {
        int iGoodWaterIndex = GetTileIndexSuitableFor(ETerrainType.grass, 1);
        if (iGoodWaterIndex != -1)
        {
            theMap.ChangeAreaToTerrain(iGoodWaterIndex, 1, ETerrainType.water);
            Vector2 vGamePos = theMap.GetVectorForTile(iGoodWaterIndex);

            vGamePos.x += 0.5f;
            vGamePos.y += 0.5f;

            theGame.PlayParticleEffect( vGamePos, Prefab_ChangingPoof);
            LDGameActor newSpawner = theGame.SpawnActorPrefab(vGamePos, Prefab_WaterSpawner);
            theGame.theAIManager.RegisterLandmark(newSpawner);
            TM_AudioManager.PlayClip(clip_NewLandmark);
            return true;
        }

        Debug.Log("Couldn't do it, i'm bad.");
        return false;
    }

    public int GetTileIndexSuitableFor(ETerrainType mustBeTerrain, int iRadiusToCheck, bool bCantBeNextToSpace = true)
    {
        int iTries = 100;

        //look near landmarks, and grow out from them
        while (iTries > 0)
        {
            iTries--;

            Vector2 vGuessPosition = theGame.theAIManager.GetRandomLandmarkLocation();
            if (vGuessPosition == Vector2.zero)
            {
                //No landmarks? Uh oh!
                return -1;
            }

            vGuessPosition.x = Random.Range(vGuessPosition.x - 10, vGuessPosition.x + 10);
            vGuessPosition.y = Random.Range(vGuessPosition.y - 10, vGuessPosition.y + 10);

            //if this is TOO close to an existing landmark, don't use it
            if (theGame.theAIManager.IsPositionNearLandmark(vGuessPosition, 2.0f))
            {
                continue;
            }


            ETerrainType checkTerrain = theMap.GetTerrainForTile(vGuessPosition);
            if (checkTerrain != mustBeTerrain)
            {
                continue;
            }

            //check all tiles within range
            bool bTileIsGood = true;
            //expand the search by 1, giving us the edge to check for bCantBeNextToSpace
            int xSpaceBorderMin = (int)vGuessPosition.x - (iRadiusToCheck + 1);
            int xSpaceBorderMax = (int)vGuessPosition.x + (iRadiusToCheck + 1);
            int ySpaceBorderMin = (int)vGuessPosition.y - (iRadiusToCheck + 1);
            int ySpaceBorderMax = (int)vGuessPosition.y + (iRadiusToCheck + 1);

            for (int x = xSpaceBorderMin; x <= xSpaceBorderMax && bTileIsGood; x++)
                for (int y = ySpaceBorderMin; y <= ySpaceBorderMax && bTileIsGood; y++)
                {
                    ETerrainType neighborTerrain = theMap.GetTerrainForTile(x, y);
                    
                    if (x == xSpaceBorderMin ||
                        x == xSpaceBorderMax ||
                        y == ySpaceBorderMin ||
                        y == ySpaceBorderMax)
                    {
                        if (bCantBeNextToSpace && neighborTerrain == ETerrainType.empty_space)
                        {
                            //immediately toss this tile out of contention
                            bTileIsGood = false;
                        }

                        continue;
                    }

                    if (neighborTerrain != mustBeTerrain)
                    {
                        bTileIsGood = false;
                    }


                }

            if (bTileIsGood)
            {
                return theMap.GetIndexForTileVector(vGuessPosition);
            }
        }

        return -1;
    }
}
