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

public class AISettings
{
    public float m_agressiveness    = 1.3f;   // 1.0 is passive and only attacks in range. 2.0 is twice the regular movement radius, etc...
    public float m_idleRoamChance   = 0.0f;   // Chance character will idly walk around. 0.0 is never. 1.0 is always (when not able to get to player).
};

public enum AttackType
{
    Melee,
    Ranged,
    Magic,
    None
};

public struct CoordChoice
{
    public GridCoord m_pos;
    public int m_stepsFromPlayer;
}

public class EnemyTurn : BaseTurn {

    const float THINK_TIME_MIN = 1.0f;
    const float THINK_TIME_MAX = 1.5f;


    float m_thinkTimeLeft;

    AISettings m_aiSettings;
    CharacterInfo m_info;

    public EnemyTurn(EnemyObject obj)
        : base(obj.GetComponent<CharacterObject>())
    {
        m_enemyObj = obj;
        m_info = m_enemyObj.GetComponent<CharacterObject>().Info;
        m_aiSettings = m_enemyObj.AI;

        if (m_info == null)
        {
            Debug.LogError("No info ");
        }
        if (m_aiSettings == null)
        {
            Debug.LogError("No info ");
        }
    }

    bool m_doneMoving = false;
    AttackType m_attackType = AttackType.None;
    int m_magicIndex = -1;

    public void StartThinking()
    {
        CharacterStatsGui.SetEnemy(m_enemyObj.transform);
        m_thinkTimeLeft = Random.Range( THINK_TIME_MIN, THINK_TIME_MAX );
    }

    public bool DoneThinking()
    {
        m_thinkTimeLeft -= Time.deltaTime;
        if ( m_thinkTimeLeft <= 0.0f )
        {
            return true;
        }
        return false;
    }

    public override void StartMoveLocPick()
    {
        StartThinking();
    }

    public List<CoordChoice> CopyListWithSteps( List<CoordChoice> srcList, int steps )
    {
        List<CoordChoice> newList = new List<CoordChoice>();
        foreach (CoordChoice choice in srcList)
        {
            if (choice.m_stepsFromPlayer == steps)
            {
                newList.Add(choice);
            }
        }
        return newList;
    }

    public override bool DoMoveChoice(out GridCoord destPos)
    {
        destPos = m_startPosition;
        if ( DoneThinking() )
        {
            if ( m_doneMoving )
            {
                Debug.LogError("AI already moved this turn!");
            }
            List<CoordChoice> possMoves = RangeHighlighter.GetPossibleMoves();

            int minRange = 100;
            int maxRange = 0;

            foreach( CoordChoice choice in possMoves )
            {
                minRange = Mathf.Min(minRange, choice.m_stepsFromPlayer);
                maxRange = Mathf.Max(maxRange, choice.m_stepsFromPlayer);
            }

            //Debug.Log(m_info.m_name + " " + minRange + " " + maxRange);

            m_attackType = m_info.PreferredAttackType(minRange, maxRange, out m_magicIndex);

            int chosenDistFromPlayer = -1;

            switch (m_attackType)
            {
                case AttackType.None:
                    {
                        GridCoord playerPos = PlayerObject.Instance.GetComponent<GridObject>().GridPosition;
                        float proxim = GridCoord.GetStraightDistanceBetween(playerPos, m_startPosition);

                        if (proxim < (m_info.m_move * m_aiSettings.m_agressiveness))
                        {
                            // Close enough to player. Try and get even closer.

                            int minSteps = 1000;
                            foreach (CoordChoice choice in possMoves)
                            {
                                if (choice.m_stepsFromPlayer < minSteps)
                                {
                                    minSteps = choice.m_stepsFromPlayer;
                                    chosenDistFromPlayer = choice.m_stepsFromPlayer;
                                }
                            }
                        }
                        else
                        {
                            if ( m_aiSettings.m_idleRoamChance > 0.0f )
                            {
                                if ( (Random.Range(0.01f, 1.0f) <= m_aiSettings.m_idleRoamChance ) )
                                {
                                    chosenDistFromPlayer = maxRange;
                                }
                            }
                        }
                    }
                    break;
                case AttackType.Melee:
                    {
                        foreach (CoordChoice choice in possMoves)
                        {
                            if (choice.m_stepsFromPlayer == 1)
                            {
                                chosenDistFromPlayer = 1;
                                break;
                            }
                        }
                    }
                    break;
                case AttackType.Ranged:
                    {
                        int maxRangeForWeapon = m_info.RangedWeapon.m_weaponMaxRange;
                        int biggestRange = 0;

                        foreach (CoordChoice choice in possMoves)
                        {
                            if (choice.m_stepsFromPlayer >= m_info.RangedWeapon.m_weaponMinRange)
                            {
                                if (choice.m_stepsFromPlayer > biggestRange )
                                {
                                    if (choice.m_stepsFromPlayer <= maxRangeForWeapon)
                                    {
                                        biggestRange = choice.m_stepsFromPlayer;
                                        chosenDistFromPlayer = choice.m_stepsFromPlayer;
                                    }
                                }
                            }
                        }
                    }
                    break;
                case AttackType.Magic:
                    {
                        CharacterMagic magic = CharacterMagic.GetMagic(m_info.m_magic[m_magicIndex]);
                        int biggestRange = 0;

                        foreach (CoordChoice choice in possMoves)
                        {
                            if (choice.m_stepsFromPlayer > biggestRange)
                            {
                                if (choice.m_stepsFromPlayer <= magic.m_range)
                                {
                                    biggestRange = choice.m_stepsFromPlayer;
                                    chosenDistFromPlayer = choice.m_stepsFromPlayer;
                                }
                            }
                        }
                    }
                    break;
            }

            if ( chosenDistFromPlayer > 0 )
            {
                List<CoordChoice> chosenMoves = CopyListWithSteps(possMoves, chosenDistFromPlayer);

                if ( chosenMoves.Count > 0 )
                {
                    // Pick randomly from list
                    destPos = chosenMoves[Random.Range(0, chosenMoves.Count)].m_pos;
                    
                    // Fix so they don't slide around needlessly
                    if (m_attackType != AttackType.None)
                    {
                        GridCoord playerPos = PlayerObject.Instance.GetComponent<GridObject>().GridPosition;

                        int newDist = GridCoord.GetStepsBetween(destPos, playerPos);
                        int curDist = GridCoord.GetStepsBetween(m_startPosition, playerPos);

                        //                 Debug.Log(destPos.x + " " + destPos.y);
                        //                 Debug.Log(m_startPosition.x + " " + m_startPosition.y);
                        //                 Debug.Log(curDist + " " + newDist);
                        if (newDist == curDist)
                        {
                            // Yeah, no point moving. Just stay here.
                            destPos = m_startPosition;
                        }
                    }
                }
            }

            if ( destPos != m_startPosition )
            {
                SFXManager.Play(SFXManager.Instance.m_enemyMove);
            }
            return true;
        }
        return false;
    }

    public override bool PlayerWantsActionMenu()
    {
        return m_doneMoving;
    }

    public override void HasMoved()
    {
        m_doneMoving = true;
    }

    public override bool MadeMenuChoiceMove(out MenuAction choice)
    {
        switch (m_attackType)
        {
            case AttackType.Ranged:
            case AttackType.Melee:
                {
                    choice = MenuAction.Attack;
                }
                break;
            case AttackType.Magic:
                {
                    choice = MenuAction.Magic;
                }
                break;
            case AttackType.None:
            default:
                {
                    choice = MenuAction.Stay;
                }
                break;
        }
        return true;
    }

    public override void StartActionLocPick()
    {
        StartThinking();
    }

    public override bool DoActionLocationPick(out GridCoord targetPos, out bool cancel)
    {
        cancel = false;
        targetPos = m_enemyObj.GetComponent<GridObject>().GridPosition;

        if (DoneThinking())
        {
            switch (m_attackType)
            {
                case AttackType.Ranged:
                case AttackType.Melee:
                case AttackType.Magic:
                    {
                        targetPos = PlayerObject.Instance.GetComponent<GridObject>().GridPosition;
                    }
                    break;
                case AttackType.None:
                default:
                    {

                    }
                    break;
            }

            StartThinking();
            return true;
        }
        return false;
    }

    public override bool MadeMenuChoiceAction(out MenuAction choice)
    {
        choice = MenuAction.Confirm;
        return DoneThinking();
    }

    public override bool MadeMagicChoice(out int choiceIndex)
    {
        choiceIndex = m_magicIndex;
        return true;
    }

    public override bool MadeItemChoice(out int choiceIndex)
    {
        choiceIndex = -1;
        return true;
    }
    public override void ShowMagicChoiceMenu()
    {

    }
    public override void ShowItemChoiceMenu()
    {

    }
    

    EnemyObject m_enemyObj;

}
