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

public class MenuController : MonoBehaviour
{
    public GameObject BrainsAnimationPrefab = null;

    private FSM fsm = null;

    void Start()
    {
        fsm = new FSM();

        // Add State

        FirstDialogState firstDialogState = new FirstDialogState("FirstDialogState");
        SecondDialogState secondDialogState = new SecondDialogState("SecondDialogState");
        ThirdDialogState thirdDialogState = new ThirdDialogState("ThirdDialogState");
        CheckJoysticksState checkJoysticksState = new CheckJoysticksState("CheckJoysticksState");
        FourthDialogState fourthDialogState = new FourthDialogState("FourthDialogState");
        CountdownState countdownState = new CountdownState("CountdownState");
        WaitForAButtonState waitForAButtonState = new WaitForAButtonState("WaitForAButtonState");
        BrainSynchingState brainSynchingState = new BrainSynchingState("BrainSynchingState", BrainsAnimationPrefab);
        ShowStatState showStatState = new ShowStatState("ShowStatState");

        fsm.AddState(firstDialogState);
        fsm.AddState(secondDialogState);
        fsm.AddState(thirdDialogState);
        fsm.AddState(checkJoysticksState);
        fsm.AddState(fourthDialogState);
        fsm.AddState(countdownState);
        fsm.AddState(waitForAButtonState);
        fsm.AddState(brainSynchingState);
        fsm.AddState(showStatState);

        fsm.SetState("FirstDialogState");
    }

    void Update()
    {
        fsm.Update(Time.deltaTime);
    }
}

#region FSM

#region Generic

public abstract class State
{
    private string _Id;

    public string Id
    {
        get { return _Id; }
    }

    public abstract void OnEnter();

    public abstract void Update(float i_DeltaTime);

    public abstract void OnExit();

    public abstract string DoTransitions();

    public State(string i_Id)
    {
        _Id = i_Id;
    }
}

public class FSM
{
    private List<State> _States;

    private State _CurrentState = null;

    public State CurrentState
    {
        get { return _CurrentState; }
    }

    public void AddState(State i_State)
    {
        _States.Add(i_State);
    }

    public void Clear()
    {
        _States.Clear();
    }

    public void Update(float i_DeltaTime)
    {
        if (_CurrentState != null)
        {
            _CurrentState.Update(i_DeltaTime);

            string newId = _CurrentState.DoTransitions();

            if (newId != "#NO" && newId != _CurrentState.Id)
            {
                SetState(newId);
            }
        }
    }

    public void SetState(string i_Id)
    {
        foreach (State s in _States)
        {
            if (s.Id == i_Id)
            {
                SetState(s);

                break;
            }
        }
    }

    private void SetState(State s)
    {
        if (_CurrentState != null)
        {
            _CurrentState.OnExit();
        }

        _CurrentState = s;

        _CurrentState.OnEnter();
    }

    public FSM()
    {
        _States = new List<State>();
    }
}

#endregion

#region States

#region First

public class FirstDialogState : State
{
    private string sentence = "Hi! I am a Volphant.";

    private Text _Text = null;

    private float _Time = 2.5f;
    private float _ElapsedTime = 0f;

    public override void OnEnter()
    {
        Transform canvas = GameObject.Find("Canvas").transform;

        if (canvas != null)
        {
            Transform balloon = canvas.FindChild("TextBalloon");

            if (balloon != null)
            {
                Transform textTransform = balloon.FindChild("Text");

                if (textTransform != null)
                {
                    _Text = (Text)textTransform.GetComponent(typeof(Text));

                    if (_Text != null)
                    {
                        _Text.text = sentence;
                    }
                }

            }
        }
    }

    public override void OnExit()
    {
        
    }

    public override void Update(float i_DeltaTime)
    {
        _ElapsedTime += i_DeltaTime;
    }

    public override string DoTransitions()
    {
        if (_ElapsedTime >= _Time)
        {
            return "SecondDialogState";
        }

        return "#NO";
    }

    public FirstDialogState(string i_Id)
        : base(i_Id)
    {

    }
}

#endregion

#region Second

public class SecondDialogState : State
{
    private string sentence = "Since my mind is too complex for human kind you are required to play with a partner in order to move me.";

    private Text _Text = null;

    private float _Time = 6f;
    private float _ElapsedTime = 0f;

    public override void OnEnter()
    {
        Transform canvas = GameObject.Find("Canvas").transform;

        if (canvas != null)
        {
            Transform balloon = canvas.FindChild("TextBalloon");

            if (balloon != null)
            {
                Transform textTransform = balloon.FindChild("Text");

                if (textTransform != null)
                {
                    _Text = (Text)textTransform.GetComponent(typeof(Text));

                    if (_Text != null)
                    {
                        _Text.text = sentence;
                    }
                }

            }
        }
    }

    public override void OnExit()
    {

    }

    public override void Update(float i_DeltaTime)
    {
        _ElapsedTime += i_DeltaTime;
    }

    public override string DoTransitions()
    {
        if (_ElapsedTime >= _Time)
        {
            return "ThirdDialogState";
        }

        return "#NO";
    }

    public SecondDialogState(string i_Id)
        : base(i_Id)
    {

    }
}

#endregion

#region Third

public class ThirdDialogState : State
{
    private string sentence = "We' ll run a simple synchro test to prove your connection.";

    private Text _Text = null;

    private float _Time = 4f;
    private float _ElapsedTime = 0f;

    public override void OnEnter()
    {
        Transform canvas = GameObject.Find("Canvas").transform;

        if (canvas != null)
        {
            Transform balloon = canvas.FindChild("TextBalloon");

            if (balloon != null)
            {
                Transform textTransform = balloon.FindChild("Text");

                if (textTransform != null)
                {
                    _Text = (Text)textTransform.GetComponent(typeof(Text));

                    if (_Text != null)
                    {
                        _Text.text = sentence;
                    }
                }

            }
        }
    }

    public override void OnExit()
    {

    }

    public override void Update(float i_DeltaTime)
    {
        _ElapsedTime += i_DeltaTime;
    }

    public override string DoTransitions()
    {
        if (_ElapsedTime >= _Time)
        {
            return "CheckJoysticksState";
        }

        return "#NO";
    }

    public ThirdDialogState(string i_Id)
        : base(i_Id)
    {

    }
}

#endregion

#region Fourth

public class CheckJoysticksState : State
{
    private bool controller1Visible = false;
    private bool controller2Visible = false;
    private bool controller3Visible = false;
    private bool controller4Visible = false;

    GameObject controller1 = null;
    GameObject controller2 = null;
    GameObject controller3 = null;
    GameObject controller4 = null;

    private Transform backgrounds = null;

    GameObject player1 = null;
    GameObject player2 = null;

    public override void OnEnter()
    {
        backgrounds = GameObject.Find("Backgrounds").transform;
        if (backgrounds != null)
        {
            Transform mono = backgrounds.FindChild("BackMonoscromo");

            if (mono != null)
            {
                mono.gameObject.SetActive(false);
            }

            Transform check = backgrounds.FindChild("BackCheck");
            
            if(check != null)
            {
                check.gameObject.SetActive(true);
            }
        }

        player1 = GameObject.Find("Player1");
        player2 = GameObject.Find("Player2");

        Transform canvas = GameObject.Find("Canvas").transform;

        if (canvas != null)
        {
            Transform balloon = canvas.FindChild("TextBalloon");

            if (balloon != null)
            {
                balloon.gameObject.SetActive(false);
            }
        }

        Transform checkJoystick = GameObject.Find("CheckJoysticks").transform;

        if (checkJoystick != null)
        {
            checkJoystick.gameObject.SetActive(true);

            controller1 = checkJoystick.FindChild("Controller1").gameObject;
            controller2 = checkJoystick.FindChild("Controller2").gameObject;
            controller3 = checkJoystick.FindChild("Controller3").gameObject;
            controller4 = checkJoystick.FindChild("Controller4").gameObject;
        }

        if (player1 != null)
        {
            player1.SetActive(false);
        }

        if (player2 != null)
        {
            player2.SetActive(false);
        }
    }

    public override void OnExit()
    {
        Transform canvas = GameObject.Find("Canvas").transform;

        if (canvas != null)
        {
            Transform check = canvas.FindChild("CheckJoysticks");

            if (check != null)
            {
                check.gameObject.SetActive(false);
            }
        }

        if (player1 != null)
        {
            player1.SetActive(true);
        }

        if (player2 != null)
        {
            player2.SetActive(true);
        }
    }

    public override void Update(float i_DeltaTime)
    {
        controller1Visible = (Input.GetButton("P1_Jump")) ? true : false;
        controller2Visible = (Input.GetButton("P2_Jump")) ? true : false;
        controller3Visible = (Input.GetButton("P3_Jump")) ? true : false;
        controller4Visible = (Input.GetButton("P4_Jump")) ? true : false;

        if (controller1 != null)
        {
            controller1.SetActive(controller1Visible);
        }

        if (controller2 != null)
        {
            controller2.SetActive(controller2Visible);
        }

        if (controller3 != null)
        {
            controller3.SetActive(controller3Visible);
        }

        if (controller4 != null)
        {
            controller4.SetActive(controller4Visible);
        }
        
    }

    public override string DoTransitions()
    {
        if (Input.GetButtonDown("P1_Start") || Input.GetButtonDown("P2_Start") || Input.GetButtonDown("P3_Start") || Input.GetButtonDown("P4_Start"))
        {
            return "FourthDialogState";
        }
        
        return "#NO";
    }

    public CheckJoysticksState(string i_Id)
        : base (i_Id)
    {
    
    }
}

#endregion

#region Five

public class FourthDialogState : State
{
    private string sentence = "Press 'A' button at the end of the countdown.";

    private Text _Text = null;

    private float _Time = 3f;
    private float _ElapsedTime = 0f;

    public override void OnEnter()
    {
        Transform canvas = GameObject.Find("Canvas").transform;

        if (canvas != null)
        {
            Transform balloon = canvas.FindChild("TextBalloon");

            if (balloon != null)
            {
                balloon.gameObject.SetActive(true);

                Transform textTransform = balloon.FindChild("Text");

                if (textTransform != null)
                {
                    _Text = (Text)textTransform.GetComponent(typeof(Text));

                    if (_Text != null)
                    {
                        _Text.text = sentence;
                    }
                }
            }
        }
    }

    public override void OnExit()
    {

    }

    public override void Update(float i_DeltaTime)
    {
        _ElapsedTime += i_DeltaTime;
    }

    public override string DoTransitions()
    {
        if (_ElapsedTime >= _Time)
        {
            return "CountdownState";
        }

        return "#NO";
    }

    public FourthDialogState(string i_Id)
        : base(i_Id)
    {

    }
}

#endregion

#region Six

public class CountdownState : State
{
    private float _Time = 3f;
    private float _ElapsedTime = 0f;

    private Text _Text = null;

    public override void OnEnter()
    {
        _Time = 3f;
        _ElapsedTime = 0f;
        
        Transform canvas = GameObject.Find("Canvas").transform;

        if (canvas != null)
        {
            Transform balloon = canvas.FindChild("TextBalloon");

            if (balloon != null)
            {
                Transform textTransform = balloon.FindChild("Text");

                if (textTransform != null)
                {
                    _Text = (Text)textTransform.GetComponent(typeof(Text));
                }

            }
        }
    }

    public override void OnExit()
    {

    }

    public override void Update(float i_DeltaTime)
    {
        float toPrint = _Time - _ElapsedTime;

        int intToPrint = (int)Mathf.Ceil(toPrint);

        SetText(intToPrint.ToString());

        _ElapsedTime += i_DeltaTime;
    }

    public override string DoTransitions()
    {
        if (_ElapsedTime >= _Time)
        {
            return "WaitForAButtonState";
        }

        return "#NO";
    }

    private void SetText(string s)
    {
        if(_Text != null)
        {
            _Text.text = s;
        }
    }

    public CountdownState(string i_Id)
        : base(i_Id)
    {

    }
}

#endregion

#region Seven

public class WaitForAButtonState : State
{
    public override void OnEnter()
    {
        Transform canvas = GameObject.Find("Canvas").transform;

        if (canvas != null)
        {
            Transform balloon = canvas.FindChild("TextBalloon");

            if (balloon != null)
            {
                Transform textTransform = balloon.FindChild("Text");
                Transform aButtonTransform = balloon.FindChild("AButton");

                if (textTransform != null)
                {
                    textTransform.gameObject.SetActive(false);
                }

                if (aButtonTransform != null)
                {
                    aButtonTransform.gameObject.SetActive(true);
                }

            }
        }
    }

    public override void OnExit()
    {

    }

    public override void Update(float i_DeltaTime)
    {

    }

    public override string DoTransitions()
    {
        if (
            (Input.GetButtonDown("P1_Jump") && Input.GetButton("P2_Jump") && Input.GetButton("P3_Jump") && Input.GetButton("P4_Jump")) ||
            (Input.GetButton("P1_Jump") && Input.GetButtonDown("P2_Jump") && Input.GetButton("P3_Jump") && Input.GetButton("P4_Jump")) ||
            (Input.GetButton("P1_Jump") && Input.GetButton("P2_Jump") && Input.GetButtonDown("P3_Jump") && Input.GetButton("P4_Jump")) ||
            (Input.GetButton("P1_Jump") && Input.GetButton("P2_Jump") && Input.GetButton("P3_Jump") && Input.GetButtonDown("P4_Jump"))
            )
        {
            return "BrainSynchingState";
        }

        return "#NO";
    }

    public WaitForAButtonState(string i_Id)
        : base(i_Id)
    {

    }
}

#endregion

#region Eight

public class BrainSynchingState : State
{
    private GameObject Brains = null;

    private float _Time = 5f;
    private float _ElapsedTime = 0f;

    private GameObject p_Brains = null;

    public override void OnEnter()
    {
        GameObject player1 = GameObject.Find("Player1");

        if (player1 != null)
        {
            GameObject.Destroy(player1);
        }

        GameObject back = GameObject.Find("BackTutorial");

        if (back != null)
        {
            GameObject.Destroy(back);
        }

        Transform canvas = GameObject.Find("Canvas").transform;

        if (canvas != null)
        {
            Transform balloon = canvas.FindChild("TextBalloon");

            if (balloon != null)
            {
                Transform aButtonTransform = balloon.FindChild("AButton");

                if (aButtonTransform != null)
                {
                    aButtonTransform.gameObject.SetActive(false);
                }

                GameObject.Destroy(balloon.gameObject);
            }
        }

        // Devo playare l animazione dei cervelli!
        if(p_Brains != null)
        {
            Brains = (GameObject)GameObject.Instantiate(p_Brains);
        }
    }

    public override void OnExit()
    {

    }

    public override void Update(float i_DeltaTime)
    {
        _ElapsedTime += i_DeltaTime;

        if (_ElapsedTime >= _Time)
        {
            if (Brains != null)
            {
                GameObject.Destroy(Brains);
            }
        }
    }

    public override string DoTransitions()
    {
        if (_ElapsedTime >= _Time)
        {
            return "ShowStatState";
        }

        return "#NO";
    }

    public BrainSynchingState(string i_Id, GameObject i_p_Brains)
        : base(i_Id)
    {
        p_Brains = i_p_Brains;
    }
}

#endregion

#region Nine

public class ShowStatState : State
{
    int t1P;
    int t2P;

    private float _Time = 3f;
    private float _ElapsedTime = 0f;

    public override void OnEnter()
    {
        Transform canvas = GameObject.Find("Canvas").transform;

        if (canvas != null)
        {
            Transform stat = canvas.FindChild("Stat");

            if (stat != null)
            {
                GenerateStat();

                Text t1Percentage = (Text) stat.FindChild("T1Percentage").gameObject.GetComponent(typeof(Text));
                Text t2Percentage = (Text) stat.FindChild("T2Percentage").gameObject.GetComponent(typeof(Text));

                if (t1Percentage != null)
                {
                    t1Percentage.text = t1P + "%";
                }

                if (t2Percentage != null)
                {
                    t2Percentage.text = t2P + "%";
                }

                stat.gameObject.SetActive(true);
            }
        }
    }

    private void GenerateStat()
    {
        t1P = Random.Range(0, 100);
        t2P = Random.Range(0, 100);
    }

    private void WriteStat()
    {
        Transform canvas = GameObject.Find("Canvas").transform;

        if (canvas != null)
        {
            Transform stat = canvas.FindChild("Stat");

            if (stat != null)
            {
                Text t1Percentage = (Text)stat.FindChild("T1Percentage").gameObject.GetComponent(typeof(Text));
                Text t2Percentage = (Text)stat.FindChild("T2Percentage").gameObject.GetComponent(typeof(Text));

                if (t1Percentage != null)
                {
                    t1Percentage.text = t1P + "%";
                }

                if (t2Percentage != null)
                {
                    t2Percentage.text = t2P + "%";
                }
            }
        }
    }

    public override void OnExit()
    {

    }

    public override void Update(float i_DeltaTime)
    {
        _ElapsedTime += i_DeltaTime;

        if (_ElapsedTime < _Time)
        {
            GenerateStat();
            WriteStat();
        }
    }

    public override string DoTransitions()
    {
        if (_ElapsedTime >= _Time)
        {
            if (Input.GetButtonDown("P1_Start") || Input.GetButtonDown("P2_Start") || Input.GetButtonDown("P3_Start") || Input.GetButtonDown("P4_Start"))
            {
                Application.LoadLevel("MainScene");
            }
        }
        return "#NO";
    }

    public ShowStatState(string i_Id)
        : base(i_Id)
    {

    }
}

#endregion

#endregion

#endregion