using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Xml.Linq;
using UnityEngine;

public class LDChangeTileWorkerComponent : LDAIDoActionComponent
{
    [Header("Building Info")] 
    public int WorkSearchRadius;
    public float SecondsToFinishConversion;
    public ETerrainType TerrainToConvertTo;
    public float MaxRangeFromLandmarkToBuild;

    private int idxTargetTileToConvert;
    private float fConvertTimeRemaining;

    private float fTimeMovingToDestination;

	public override void Start () 
    {
        base.Start();
	}
	
	// Update is called once per frame
	void Update () 
    {
		
	}

    //Find a tile that needs our love
    public override bool FigureOutWhereToGo()
    {
        //look at bunch of tiles near us, if any of them are
        // GRASS
        // adjacent to 
        // EMPTY SPACE
        //
        // then we should consider it.
        Vector2 vCurrentPos = myOwningActor.vWorldPos;
        
        float fBestSqDistance = float.MaxValue;
        int iClosestIndex = -1;
        Vector2 vBestDestination = new Vector2(0,0);

        //Sometimes we just feel a need to build out to the east
        //TODO: if there's an enemy faction, reverse this
        bool bShouldThinkEastThoughtsToday = Random.value < 0.1f;

        for(int x = (int)vCurrentPos.x - WorkSearchRadius; x <= vCurrentPos.x + WorkSearchRadius; x++)
            for (int y = (int) vCurrentPos.y - WorkSearchRadius; y <= vCurrentPos.y + WorkSearchRadius; y++)
            {
                //if it is out of bounds, say no
                if (x < 5 ||
                    x > theGame.theWorld.Width - 6 ||
                    y < 5 ||
                    y > theGame.theWorld.Height - 6 
                )
                {
                    continue;
                }

                if (bShouldThinkEastThoughtsToday &&
                    (x < vCurrentPos.x + 1))
                {
                    continue;
                }

                //if we're too far from any landmarks, don't build there
                if (!theGame.theAIManager.IsPositionNearLandmark(new Vector2(x, y), MaxRangeFromLandmarkToBuild))
                {
                    continue;
                }

                ETerrainType checkTile = theGame.theWorld.GetTerrainForTile(x, y);
                if (checkTile != ETerrainType.empty_space)
                {
                    continue;
                }


                for (ECompassDirection dir = ECompassDirection.north; dir < ECompassDirection.max; dir++)
                {
                    int iNeighborIndex = theGame.theWorld.GetTileNeighborIndex(x, y, dir);
                    if (theGame.theWorld.GetTerrainForTile(iNeighborIndex) == ETerrainType.grass)
                    {
                        //Don't take a tile someone else is working on
                        if (theGame.theAIManager.TileIsBusyForBuilding(iNeighborIndex))
                        {
                            continue;
                        }

                        //cool, is this the closest? Do we even care?
                        bool bClosestSchmosest = false; // Random.value < 0.05f;

                        float fSqDist = theGame.theWorld.SqDistFromVectorToTile(vCurrentPos, iNeighborIndex);
                        if (fSqDist < fBestSqDistance || bClosestSchmosest )
                        {
                            fBestSqDistance = fSqDist;
                            iClosestIndex = iNeighborIndex;
                        }
                    }
                }
            }

        if (iClosestIndex == -1)
        {
            return false;
        }

        idxTargetTileToConvert = iClosestIndex;

        vGoalLocation = theGame.theWorld.GetVectorForTile(idxTargetTileToConvert);
        vGoalLocation.x += 0.5f;
        vGoalLocation.y += 0.5f;

        if (theGame.theWorld.GetTerrainForTile(vGoalLocation) != ETerrainType.grass)
        {
            Debugger.Break();
        }

        return true;

    }

    public bool IsWorkingOnTile(int iTileIdx)
    {
        return idxTargetTileToConvert == iTileIdx;
    }

    public override string GetThoughtText()
    {
        string sGoalTerrain = "Goal " + vGoalLocation.ToString() + " " + theGame.theWorld.GetTerrainForTile(vGoalLocation);
        return sGoalTerrain;
    }

    public override ECreatureAIState TakeAction(ECreatureAIState myState)
    {
        Vector2 vCurrentPos = myOwningActor.vWorldPos;
        float fSqDist = (vGoalLocation - vCurrentPos).SqrMagnitude();

        switch (myState)
        {
            case ECreatureAIState.moving_to_work:

                //if I'm close enough, switch to working.
                if (fSqDist <= 0.25f * 0.25f)
                {
                    //start working
                    if (StartWorkingOnConversion())
                    {
                        return ECreatureAIState.working;
                    }
                    else
                    {
                        return ECreatureAIState.chillin;
                    }
                }
                return ECreatureAIState.moving_to_work;
            case ECreatureAIState.working:
                if (DoWork())
                {
                    return ECreatureAIState.chillin;
                }
                return ECreatureAIState.working;
        }
        return myState;
    }

    bool StartWorkingOnConversion()
    {
        //find a space near us that is empty space
        bool bFoundSpace = false;
        for (ECompassDirection dir = ECompassDirection.north; dir < ECompassDirection.max; dir++)
        {
            int iNeighborIndex = theGame.theWorld.GetTileNeighborIndex(idxTargetTileToConvert, dir);
            if (theGame.theWorld.GetTerrainForTile(iNeighborIndex) == ETerrainType.empty_space)
            {
                idxTargetTileToConvert = iNeighborIndex;
                bFoundSpace = true;
                break;
            }
        }

        if (!bFoundSpace)
        {
            return false;
        }

        fConvertTimeRemaining = SecondsToFinishConversion;
        return true;
    }

    bool DoWork()
    {
        fConvertTimeRemaining -= Time.deltaTime;
        if (fConvertTimeRemaining <= 0f)
        {
            if (theGame.theWorld.GetTerrainForTile(idxTargetTileToConvert) != TerrainToConvertTo)
            {
                theGame.theWorld.ChangeTileToTerrain(idxTargetTileToConvert, TerrainToConvertTo);
                //theGame.PlaySummoningPoof(theGame.theWorld.GetVectorForTile(idxTargetTileToConvert));
                theGame.UpdateWorldFromTileChange();

                theGame.OnAddNewLand();
            }
            return true;
        }

        return false;

    }

    public override void OnRegisterAI()
    {
        theGame.theAIManager.RegisterAsBuilder(this);
    }
}
