using UnityEngine;
using System.Collections;

public class PlayerController : MonoBehaviour
{
    public enum MoveType
    {
        Attack,
        Defend,
        Ritual,
    }

    public PlayerController CurrentTarget;
    public KeyCode[] PadInputs;
    public KeyCode[] KeyInputs;

    public GameObject[] DemonPrefabs;
    public GameObject[] WizardPrefabs;
    public PlayerInputDisplay InputDisplay;

    // Private fields

    private int _currentHealth;
    private int _maxRitual;
    private int _currentRitualLevel;
    private MoveType? _nextMove;
    //   private bool _damageTaken;
    private int _currentDamagedPieceIndex;

    private Tower _tower;
    private SummonArea _summonArea;

    private static int MoveTypeCount;

    private bool _turnActive;

    static PlayerController()
    {
        MoveTypeCount = System.Enum.GetValues(typeof(MoveType)).Length;
    }

    // Use this for initialization
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }

    public void Initialise(int health, int maxRitualLevel, int startingRitualLevel)
    {
        _currentHealth = health;
        _maxRitual = maxRitualLevel;
        _currentRitualLevel = startingRitualLevel;
        _nextMove = null;
        _currentDamagedPieceIndex = -1;
    }

    // Public methods.

    public void SetPlayerObjects(SummonArea summonArea, Tower tower)
    {

        _tower = tower;
        _summonArea = summonArea;

        _tower.Init(_currentHealth, WizardPrefabs);
        _summonArea.Init(_maxRitual, _currentRitualLevel, DemonPrefabs);
    }

    public void SetNextMove(MoveType move)
    {
        _nextMove = move;
    }

    public MoveType? GetNextMove()
    {
        return _nextMove;
    }

    public bool IsDead()
    {
        return _currentHealth == 0;
    }

    public bool IsSummoning()
    {
        return _currentRitualLevel == _maxRitual;
    }

    public bool IsTurnActive()
    {
        return _turnActive;
    }

    public void UpdateInput()
    {
        for (var i = 0; i < MoveTypeCount; i++)
        {
            if (Input.GetKeyDown(KeyInputs[i]) || Input.GetKeyDown(PadInputs[i]))
            {
                _nextMove = (MoveType)i;
                InputDisplay.SetPendingMove((MoveType)i);
            }
        }
    }

    public void TakeDamage(int damage)
    {
        if (_nextMove == MoveType.Defend)
        {
            CurrentTarget.TakeDamage(damage);
        }
        else
        {
            _currentHealth = Mathf.Max((_currentHealth - damage), 0);
            _currentDamagedPieceIndex = Random.Range(0, _currentHealth);
        }
    }

    public void TakeSummonDamage()
    {
        if (!IsSummoning())
        {
            _currentHealth = 0;
        }
    }

    public void IncreaseRitualLevel(int amount)
    {
        if (_currentDamagedPieceIndex >= 0)
        {
            _currentRitualLevel = 0;
        }
        else
        {
            _currentRitualLevel = Mathf.Min((_currentRitualLevel + amount), _maxRitual);
        }
    }

    public void EndTurn()
    {
        _turnActive = true;

        StartCoroutine(EndTurnCoroutine());
    }

    public IEnumerator EndTurnCoroutine()
    {
        var wizard = _tower.GetWizard();
        var demon = _summonArea.GetDemon();
        wizard.SetPlayer(this);
        demon.SetPlayer(this);

        if (_nextMove != null)
        {
            switch (_nextMove)
            {
                case MoveType.Attack:
                    {
                        wizard.SetState(Wizard.State.Attack);

                       yield return null;

                        while (wizard.IsStateActive(Wizard.State.Attack))
                        {
                            yield return null;
                        }
                        Debug.Log(name + " Attack Done");

                    }
                    break;

                case MoveType.Defend:
                    {
                        wizard.SetState(Wizard.State.Defend);

                        yield return null;

                        while (wizard.IsStateActive(Wizard.State.Defend))
                        {
                            yield return null;
                        }

                        Debug.Log(name + " Defend Done");
                    }
                    break;

                case MoveType.Ritual:
                    {
                        wizard.SetState(Wizard.State.Ritual);

                        yield return null;

                        while (wizard.IsStateActive(Wizard.State.Ritual))
                        {
                            yield return null;
                        }

                        Debug.Log(name + " Ritual Done");

                    }
                    break;
            }
        }
        else
        {
            // no move selected.
        }

        // Wait for hurt/dying state

        if (_currentDamagedPieceIndex >= 0)
        {
            _tower.DestroyPiece(_currentDamagedPieceIndex);
        }

        while (wizard.IsStateActive(Wizard.State.Hurt) || wizard.IsStateActive(Wizard.State.Dying))
        {
            yield return null;
        }

        yield return null;

        if (IsSummoning())
        {
            demon.SetState(Demon.State.Appear);

            yield return null;
            
            while (demon.IsStateActive(Demon.State.Appear))
            {
                yield return null;
            }

            if (CurrentTarget.IsSummoning())
            {
                demon.SetState(Demon.State.AttackDemon);

                yield return null;

                while (demon.IsStateActive(Demon.State.AttackDemon))
                {
                    yield return null;
                }

                demon.SetState(Demon.State.Dying);

                yield return null;

                while (demon.IsStateActive(Demon.State.Dying))
                {
                    yield return null;
                }
            }
            else
            {
                demon.SetState(Demon.State.AttackTower);

                yield return null;

                while (demon.IsStateActive(Demon.State.AttackTower))
                {
                    
                    yield return null;
                }

                CurrentTarget.DestroyTower();

                demon.SetState(Demon.State.Idle);
            }

            _currentRitualLevel = 0;
        }

        _nextMove = null;
        _currentDamagedPieceIndex = -1;

        _summonArea.SetRitualLevel(_currentRitualLevel);

        _turnActive = false;
    }

    public void DestroyTower()
    {
        _tower.DestroyTower();
    }
}
