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



public class GameMgr : MonoBehaviour
{
	public GameObject mainMenu;
	public GameObject creditMenu;
	public GameObject inGameMenu;
    public GameObject temple;
    public GameObject barManager;
	public GameObject winMenu;
    public GameObject messageText;
    public GameObject background;
	public GameObject tutorialMenu;

    public List<StealableObject> stealables = new List<StealableObject>();
    public int culpritsPerTheft = 7;

	[HideInInspector] public int[] colArray = new int[4] { 0, 1, 2, 3 };
	[HideInInspector] public Vector3[] quadrantsCenters = new Vector3[4]; 



	public static GameMgr instance = null;

	[Header("Game Parameters")]
	public float actionDelay;
	public Color[] colors;

	public float maxHeight;
	public float maxWidth;

	
	FiniteStateMachine<GameMgr> 				m_Fsm;
	Dictionary<string, FSMState<GameMgr>> 		m_States;


	private void Awake()
	{
		if(instance == null)
			instance = this;

		m_States = new Dictionary<string, FSMState<GameMgr>>()
		{
			{"main",  new IdleState()}, 
			{"credits",  new CreditsState()},
			{"game", new GameState()}, 
			{"win", new WinState()}, 
			{"tuto", new TutorialState()}, 
		};
		m_Fsm = new FiniteStateMachine<GameMgr>();
		m_Fsm.configure(this, m_States["main"]);

		init();
	}

	private void init()
	{
		float width = maxWidth;
        float height = maxHeight;

        float horStep = width / 4;
        float vertStep = height / 4;

		quadrantsCenters[0] = new Vector3(horStep, vertStep, 0f);
		quadrantsCenters[1] = new Vector3(-horStep, vertStep, 0f);
		quadrantsCenters[2] = new Vector3(horStep, -vertStep, 0f);
        quadrantsCenters[3] = new Vector3(-horStep, -vertStep, 0f);
	}


	#region UI_CALLBACKS
	public void toCredit()
	{
		m_Fsm.changeState(m_States["credits"]);
        temple.SetActive(false);
    }

	public void toMainMenu()
	{
		m_Fsm.changeState(m_States["main"]);
        temple.SetActive(false);
    }

	public void toGame()
	{
		m_Fsm.changeState(m_States["game"]);
        temple.SetActive(true);
    }

	public void toWin(string message)
	{        
        if (message == "player2Win")
        {
            SoundManager.PlaySfx(SoundManager.Sfx.sfx_accusa_officiante);
            SoundManager.ChangePhase(SoundManager.Phase.EndingSectWins);
        } 
        else if (message == "complete")
        {
            SoundManager.PlaySfx(SoundManager.Sfx.sfx_compimento_rito);
            SoundManager.PlaySfx(SoundManager.Sfx.sfx_demone);
            SoundManager.ChangePhase(SoundManager.Phase.EndingSectWins);
        }
        else if (message == "player1Win")
        {
            SoundManager.PlaySfx(SoundManager.Sfx.sfx_accusa_officiante);
            SoundManager.ChangePhase(SoundManager.Phase.EndingInfiltratorWins);
        }
        m_Fsm.changeState(m_States["win"]);
		//winMenu.GetComponentInChildren<Text>().text = message;

		if(message.Equals("complete"))
		{
			gameObject.transform.GetChild(0).gameObject.SetActive(true);
			winMenu.transform.GetChild(0).gameObject.SetActive(true);
		}
		if(message.Equals("player2Win"))
		{
			winMenu.transform.GetChild(1).gameObject.SetActive(true);
		}
		if(message.Equals("player1Win"))
		{
			winMenu.transform.GetChild(2).gameObject.SetActive(true);
		}
	}

	public void toTuto()
	{
		m_Fsm.changeState(m_States["tuto"]);
	}


	public void sendActionOne()
	{
		shuffleColors();
        SoundManager.PlaySfx(SoundManager.Sfx.sfx_spostamento_colore);
        StartCoroutine(sendDelayedAction(actionDelay, "doActionOne"));
	}


	public void sendActionTwo()
	{
        SoundManager.PlaySfx(SoundManager.Sfx.sfx_spostamento_libero);
        StartCoroutine(sendDelayedAction(actionDelay, "doActionTwo"));
	}


	public void sendActionThree()
	{
        SoundManager.PlaySfx(SoundManager.Sfx.sfx_spostamento_quadrato);
        StartCoroutine(sendDelayedAction(actionDelay, "doActionThree"));
	}

	public void sendActionFour()
	{
        SoundManager.PlaySfx(SoundManager.Sfx.sfx_ordine_inginocchiamento);
        StartCoroutine(sendDelayedAction(actionDelay, "doActionFour"));
	}

	public void sendActionFive()
	{
        SoundManager.PlaySfx(SoundManager.Sfx.sfx_ordine_alzata_fiaccola);
        StartCoroutine(sendDelayedAction(actionDelay, "doActionFive"));
	}
	#endregion

	public void registerStealable(StealableObject stealable)
	{
		stealables.Add(stealable);
	}

	public void stealObject(StealableObject stealable)
	{
		stealable.stolen = true;
	}

	public IEnumerator setTemporaryMessage(string text)
	{
		messageText.SetActive(true);
		//messageText.GetComponent<Text>().text = text;
		yield return new WaitForSeconds(3f);
		messageText.SetActive(false);
	}

	protected void shuffleColors()
	{
		for(int i = 0; i<20; i++)
		{
			int rdm = UnityEngine.Random.Range(1, colArray.Length);
			int temp = colArray[rdm];
			colArray[rdm] = colArray[0];
			colArray[0] = temp;
		}
        //Debug.Log("Shuffled colors: " + colArray[0] + " " + colArray[1] + " " + colArray[2] + " " + colArray[3]);
	}

    public Vector3 GetQuadrantCenterByColor(int color)
    {
        for (int i = 0; i < colArray.Length; i++)
        {
            if (colArray[i] == color)
                return quadrantsCenters[i];
        }
        return Vector3.zero; // should not happen
    }

    public Vector3 GetQuadrantCenterByPosition(Vector2 p) // heavy but safe!
    {
        float minDistance = float.MaxValue;
        int bestI = 0;
        for (int i = 0; i < quadrantsCenters.Length; i++)
        {
            float distance = (p - (Vector2)quadrantsCenters[i]).magnitude;
            if (distance < minDistance)
            {
                minDistance = distance;
                bestI = i;
            }
        }
        return quadrantsCenters[bestI];

    }

    public Vector3 getRandomPos(int color)
	{

        Vector3 center = GetQuadrantCenterByColor(color);

		float randX = UnityEngine.Random.Range(-maxWidth / 4, maxWidth / 4);
		float randY = UnityEngine.Random.Range(-maxHeight / 4, maxHeight / 4);
		return new Vector3(center.x + randX, center.y + randY, 0f);
	}

    public bool GetWhirlSense(int color)
    {
        Vector3 center = GetQuadrantCenterByColor(color);
        return ((center.x > 0) == (center.y > 0)); // same sign
    }

    public bool GetWhirlSense(Vector3 p)
    {
        Vector3 center = GetQuadrantCenterByPosition(p);
        return ((center.x > 0) == (center.y > 0)); // same sign
    }


    private IEnumerator sendDelayedAction(float delay, string actionStr)
	{
        barManager.BroadcastMessage(actionStr);
        yield return new WaitForSeconds(delay);
		temple.BroadcastMessage(actionStr);
        if (actionStr == "doActionTwo" || actionStr == "doActionThree")
        {
            SoundManager.PlaySfx(SoundManager.Sfx.sfx_fruscio_tonache_adepti);
        }
        else if (actionStr == "doActionOne")
        {
            SoundManager.PlaySfx(SoundManager.Sfx.sfx_mormorio_adepti);
        }
        else if (actionStr == "doActionFour")
        {
            SoundManager.PlaySfx(SoundManager.Sfx.sfx_inginocchiamento);
        }
        else if (actionStr == "doActionFive")
        {
            SoundManager.PlaySfx(SoundManager.Sfx.sfx_alzata_fiaccola);
        }

    }

    public void Suspect()
    {
        barManager.BroadcastMessage("Suspect");
    }

	private class IdleState : FSMState<GameMgr> 
	{
		public override void enter (GameMgr entity)
		{
			entity.mainMenu.SetActive(true);
            SoundManager.ChangePhase(SoundManager.Phase.Intro);
        }

		public override void exit (GameMgr entity)
		{
			entity.mainMenu.SetActive(false);
		}
	}

	private class CreditsState : FSMState<GameMgr>
	{
		public override void enter (GameMgr entity)
		{
			entity.creditMenu.SetActive(true);
		}

		public override void exit (GameMgr entity)
		{
			entity.creditMenu.SetActive(false);
		}
	}

	private class GameState : FSMState<GameMgr>
	{
		public override void enter (GameMgr entity)
		{
			entity.inGameMenu.SetActive(true);
            SoundManager.ChangePhase(SoundManager.Phase.Scene);
        }

		public override void exit (GameMgr entity)
		{
			entity.inGameMenu.SetActive(false);
		}
	}

	private class WinState : FSMState<GameMgr>
	{
		public override void enter(GameMgr entity)
		{
			entity.winMenu.SetActive(true);
		}

		public override void exit (GameMgr entity)
		{
			entity.winMenu.SetActive(false);
		}
	}

	private class TutorialState : FSMState<GameMgr>
	{
		public override void enter(GameMgr entity)
		{
			entity.tutorialMenu.SetActive(true);
		}

		public override void exit (GameMgr entity)
		{
			entity.tutorialMenu.SetActive(false);
		}
	}

    public bool CanClickIcons()
    {
        return (barManager.GetComponent<SliderManager>().IsOverMinThreshold());
    }

    public bool CanAccuse()
    {
        return (barManager.GetComponent<SliderManager>().IsOverAccusationThreshold());
    }

    public void WrongAccusation()
    {
        barManager.GetComponent<SliderManager>().AccuseInnocent();
    }

}



