using UnityEngine;
using mgaia.Utils;
using mgaia.Utils.LayerSystem;
using mgaia.Utils.Text;
using mgaia.tk2d;

public class MainView : IInputReceivable
{
    [SerializeField]
    private Postman _postman;

    [SerializeField]
    private tk2dTextMesh _turnText;

    [SerializeField]
    private LetterAndFrameContainer _letterAndFrameContainer;

    [SerializeField]
    private LetterContainer _letterContainer;

    [SerializeField]
    private ClosedLetter _closedLetter;

    [SerializeField]
    private OpenedLetter _openedLetter;

    [SerializeField]
    private GameObject[] _choicesButtons;

    [SerializeField]
    private GameObject _okButton;

    private GameMatch mGameMatch;
    private Letter mCurrentLetter;
    private bool mGameOverOcurred;
    private Choice[] mChoices;
    private bool mIsFirstLetter;
    private float mTurnWidth;
    private int mNumberOfLinesInTurn;

    public override void OnDataPackReceived(object dataPack)
    {
        Assert.AssertTrue(dataPack is GameMatch, "dataPack precisa ser GameMatch!");

        mGameMatch = (GameMatch)dataPack;
        mGameMatch.RequestLetterArrived += OnRequestLetterArrived;
        mGameMatch.ResponseLetterArrived += OnResponseLetterArrived;
        mGameMatch.MonthChanged += OnMonthChanged;
        mGameMatch.OnGameOver += OnGameOver;

        mTurnWidth = _turnText.GetEstimatedMeshBoundsForString(_turnText.text).size.x;
        mNumberOfLinesInTurn = _turnText.text.GetNumberOfLines();
        SetTurn(mGameMatch.CurrentMonth);

        for (int idx = 0; idx < _choicesButtons.Length; idx++)
        {
            RegisterButtonAction(_choicesButtons[idx].name, (gameobject) => { }, (gameobject) =>
            {
                Choose(_choicesButtons.IndexOf(gameobject));
            });
        }

        RegisterButtonAction(_okButton.name, (gameobject) => { }, (gameobject) =>
        {
            ReadResponse();
        });
    }

    private void OnGameOver(Indicators indicator)
    {
        mGameOverOcurred = true;

        string text = null;

        switch (indicator)
        {
            case Indicators.Popularity:
                text = "And thus ends your reign. Hated by your people, despised by the noble and known everywhere as a weak and coward king, you are deposed and sent to the guillotine. Not a single tear is shed as your head rolls, announcing the end of an era.";
                break;
            case Indicators.Warpower:
                text = "And thus falls a once mighty kingdom. With no armies left to defend the castle and the all the walls lying in ruins, your enemies easily invaded your lands from all sides and destroyed what little was left of your empire.";
                break;
            case Indicators.Wealthy:
                text = "And thus falls your empire. Drowned in debts, you watch your decadent city from the window of your crumbling castle as people leave to find a better life elsewhere. With the little gold you have left, you flee to a distant land where you may someday forget the shame of your past days.";
                break;
        }

        GameObject gameOverView = ViewLoader.LoadView(Views.GameOverView);
        LayerManager.Instance.AddLayerOnTop(gameOverView, true, text);
    }

    private void OnMonthChanged(int month)
    {
        SetTurn(month);

        Sound.PlayTrumpet();
    }

    private void Start()
    {
        mGameOverOcurred = false;
        mIsFirstLetter = true;
        _postman.Prepare();
        mGameMatch.Initiate();
    }

    private void ReadResponse()
    {
        mGameMatch.HandlePlayerDidPressOk();

        DismissAndGetNextLetter();
    }

    private void Choose(int index)
    {
        mGameMatch.HandlePlayerDidChoose(index);

        DismissAndGetNextLetter();
    }

    private void OnResponseLetterArrived(ResponseLetter responseLetter)
    {
        SetCurrentLetter(responseLetter, null);
    }

    private void OnRequestLetterArrived(RequestLetter requestLetter, Choice[] choices)
    {
        SetCurrentLetter(requestLetter, choices);
    }

    private void SetTurn(int month)
    {
        _turnText.text = string.Format("TURN {0}", month);
        TextMeshFormatter.FormatTextMesh(new Tk2dTextMeshContainer(_turnText), mNumberOfLinesInTurn, mTurnWidth, true);
    }

    private void SetCurrentLetter(Letter letter, Choice[] choices)
    {
        mCurrentLetter = letter;
        mChoices = choices;

        if (mIsFirstLetter)
        {
            mIsFirstLetter = false;

            RunPostman();
        }
    }

    private void DismissAndGetNextLetter()
    {
        if (!mGameOverOcurred)
        {
            _postman.Prepare();

            _letterContainer.SetLetterVisibility(LettersVisibilty.ClosedLetter);
            _closedLetter.Prepare(ClosedLetterAnimations.Closing, null);
            _closedLetter.Close(delegate()
            {
                _letterAndFrameContainer.Run(LetterAndFrameAnimations.ShowHall, delegate()
                {
                    RunPostman();
                });
            });
        }
    }

    private void RunPostman()
    {
        _postman.Run(delegate()
        {
            _letterContainer.SetLetterVisibility(LettersVisibilty.ClosedLetter);

            _closedLetter.Prepare(ClosedLetterAnimations.Opening, mCurrentLetter.RelatedAttribute);
            _openedLetter.SetLetter(mCurrentLetter, mChoices);

            _letterAndFrameContainer.Run(LetterAndFrameAnimations.ShowLetter, delegate()
            {
                _closedLetter.Open(delegate()
                {
                    _letterContainer.SetLetterVisibility(LettersVisibilty.OpenedLetter);

                    Sound.PlayVoice(mCurrentLetter.RelatedAttribute);
                });
            });
        });
    }

    private void OnDestroy()
    {
        mGameMatch.RequestLetterArrived -= OnRequestLetterArrived;
        mGameMatch.ResponseLetterArrived -= OnResponseLetterArrived;
        mGameMatch.MonthChanged -= OnMonthChanged;
        mGameMatch.OnGameOver -= OnGameOver;
    }
}