using UnityEngine;
using System;
using System.Collections.Generic;
using mgaia.Utils;

public class GameMatch
{
    public delegate void GameMonthChangedHandler(int month);
    public delegate void GameRequestLetterArrivedHandler(RequestLetter requestLetter, Choice[] choices);
    public delegate void GameResponseLetterArrivedHandler(ResponseLetter responseLetter);
    public delegate void GameOverHandler(Indicators indicator);

    public event GameMonthChangedHandler MonthChanged;
    public event GameRequestLetterArrivedHandler RequestLetterArrived;
    public event GameResponseLetterArrivedHandler ResponseLetterArrived;
    public event GameOverHandler OnGameOver;

    private int _mCurrentMonth;

    private AttributeElector mAttributeElector;
    private RequestLetter mRequestLetter;
    private ResponseLetter mResponseLetter;
    private Dictionary<int, List<ResponseLetter>> mScheduledResponseLetters = new Dictionary<int,List<ResponseLetter>>();

    private AttributeManager _mAttributeManager;

    public AttributeManager AttributeManager
    {
        get { return _mAttributeManager; }
    }

    public int CurrentMonth
    {
        get { return _mCurrentMonth; }
    }

    public GameMatch()
    {
        _mCurrentMonth = 1;
        _mAttributeManager = new AttributeManager();
        mAttributeElector = new AttributeElector();
    }

    public void Initiate()
    {        
        RequestRequestLetter();
    }

    private void RequestRequestLetter()
    {
        Attributes attribute = mAttributeElector.GetNextAttribute();
        mRequestLetter = RequestLetterManager.GetAndCheckRequestLetter(attribute, AttributeManager.GetAttributeInfluenceLevel(attribute));
        
        List<Choice> choices = new List<Choice>();
        choices = mRequestLetter.Choices;

        if (RequestLetterArrived != null)
        {
            RequestLetterArrived(mRequestLetter, choices.ToArray());
        }

        Debug.Log("Request Letter: " + mRequestLetter.TextBody);
        mRequestLetter.Choices.ForEach(choice => Debug.Log("Choice: " + choice.TextBody));
    }

    public void HandlePlayerDidChoose(int choiceIndex)
    {
        Assert.AssertTrue(mRequestLetter != null && mRequestLetter.Choices.Count > choiceIndex, "");

        Choice choice = mRequestLetter.Choices[choiceIndex];
        AttributeManager.ConsumeChoice(choice);

        if (!CheckGameOver())
        {
            ResponseLetter responseLetter;
            if (choice.TryGetSpawnedResponseLetter(out responseLetter))
            {
                int targetMonth = CurrentMonth + responseLetter.MonthsToArrive;
                if (!mScheduledResponseLetters.ContainsKey(targetMonth))
                {
                    mScheduledResponseLetters[targetMonth] = new List<ResponseLetter>();
                }
                mScheduledResponseLetters[targetMonth].Add(responseLetter);
            }
            CloseMonth();
        }
    }

    public void HandlePlayerDidPressOk()
    {
        Assert.AssertTrue(mResponseLetter != null, "");
        AttributeManager.ConsumeResponseLetter(mResponseLetter);

        if (!CheckGameOver())
        {
            if (!TryAssignNextResponseLetter())
            {
                RequestRequestLetter();
            }
        }
    }

    private bool CheckGameOver()
    {
        foreach(Indicators indicator in Enum.GetValues(typeof(Indicators)))
        {
            float value = AttributeManager.GetIndicator(indicator);
            if (value.Aproximate(0.0f))
            {
                if (OnGameOver != null)
                {
                    OnGameOver(indicator);
                }

                return true;
            }
        }
        
        return false;
    }

    private void CloseMonth()
    {
        _mCurrentMonth++;

        if (MonthChanged != null)
        {
            MonthChanged(CurrentMonth);
        }

        if (!TryAssignNextResponseLetter())
        {
            RequestRequestLetter();
        }
    }

    private bool TryAssignNextResponseLetter()
    {
        if (mScheduledResponseLetters.ContainsKey(CurrentMonth))
        {
            if (mScheduledResponseLetters[CurrentMonth].Count > 0)
            {
                mResponseLetter = mScheduledResponseLetters[CurrentMonth][0];
                mScheduledResponseLetters[CurrentMonth].RemoveAt(0);

                if (ResponseLetterArrived != null)
                {
                    ResponseLetterArrived(mResponseLetter);
                }

                Debug.Log("Response Letter: " + mResponseLetter.TextBody);

                return true;
            }
        }
        return false;
    }
}