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

public class GameManager : MonoBehaviour {

    public Player mPlayer;

    public int SequenceTimer;
    [HideInInspector] public int CurrentSequenceTimer;
    private float mDeltaTime;
    public Text TextTime;
    public Text TextSequence;

    [HideInInspector] public char[] Sequence;
    public int KeysPerCharacter = 3;

    private char[,] mBaseKeys = { { 'Q', 'W', 'E', 'R' },   //character 1
                        { 'A', 'S', 'D', 'F' },     //character 2
                        { 'U', 'I', 'O', 'P' },     //character 3
                        { 'J', 'K', 'L', 'H' } };   //character 4
    [HideInInspector] public int[] mSetOrder; //4 sets (or characters)
    [HideInInspector] public int[] mKeyOrder; //4 keys (or buttons)

    public event System.Action Event_TimerIsZero;
    public event System.Action Event_NewSequence;

    public TextMesh[] KeyTexts;

    public bool InputEnabled;
    public AudioClip music;
    public bool PlayMusic;

    // Use this for initialization
    void Awake () {
        NewGame();
	}
	
	// Update is called once per frame
	void Update () {
        UpdateTimer();	
    }

    public void NewGame()
    {
        Event_TimerIsZero += NewSequence;
        ResetTimer();
        ResetKeyOrder();
        ResetSetOrder();
        if (PlayMusic)
        {
            AudioManager.instance.PlayMusic(music);
        }
        NewSequence();
    }

    #region TIMER
    void UpdateTimer()
    {
        mDeltaTime += Time.deltaTime;
        if (mDeltaTime > 1)
        {
            mDeltaTime = 0;
            CurrentSequenceTimer--;
            UpdateTimerText();
        }
        if (CurrentSequenceTimer == 0)
        {
            if (Event_TimerIsZero != null)
            {
                Event_TimerIsZero();
                ResetTimer();
            }
        }
    }
    public void ResetTimer()
    {
        CurrentSequenceTimer = SequenceTimer;
        UpdateTimerText();
    }
    void UpdateTimerText()
    {
        TextTime.text = "Time: " + CurrentSequenceTimer.ToString();
    }
    #endregion

    #region SEQUENCE
    public void NewSequence()
    {
        int noOfCharacters = mBaseKeys.GetLength(0);
        Sequence = new char[noOfCharacters * KeysPerCharacter];

        for (int c = 0; c < noOfCharacters; c++)
        {
            for (int key = 0; key < KeysPerCharacter; key++)
            {
                Sequence[c * KeysPerCharacter + key] = mBaseKeys[mSetOrder[c], mKeyOrder[key]];
            }
        }

        string showSequence = "";
        int n = 0;
        int k = 0;
        while (n < Sequence.Length)
        {
            if ((k+1) % (KeysPerCharacter+1) == 0)
            {
                showSequence = showSequence.Insert(k, " ");
            }
            else
            {
                showSequence = showSequence.Insert(k, Sequence[n].ToString());
                n++;
            }
            k++;
        }
        //TextSequence.text = "Sequence: " + showSequence;
        UpdateSequenceText();
        if (InputEnabled)
        {
            mPlayer.ReceivingSequence(Sequence);
        }
        if (Event_NewSequence != null)
        {
            Event_NewSequence();
        }
    }

    public void HideSequenceText()
    {
        for (int i = 0; i < KeyTexts.Length; i++)
        {
            KeyTexts[i].gameObject.SetActive(false);
        }
    }
    public void ShowSequenceText()
    {
        for (int i = 0; i < KeyTexts.Length; i++)
        {
            KeyTexts[i].gameObject.SetActive(true);
        }
    }
    public void UpdateSequenceText()
    {
        for (int i = 0; i < KeyTexts.Length; i++)
        {
            KeyTexts[i].text = Sequence[i].ToString();
        }
    }
    public void ResetKeyOrder()
    {
        mKeyOrder = new int[mBaseKeys.GetLength(1)];
        for (int i = 0; i < mKeyOrder.Length; i++)
        {
            mKeyOrder[i] = i;
        }
    }
    public void ResetSetOrder()
    {
        mSetOrder = new int[mBaseKeys.GetLength(0)];
        for (int i = 0; i < mSetOrder.Length; i++)
        {
            mSetOrder[i] = i;
        }
    }
    public void ShuffleKeyOrder()
    {
        /*int TotalKeysPerCharacter = mBaseKeys.GetLength(1);
        for (int c = 0; c < mBaseKeys.GetLength(0); c++)
        {
            for (int key = 0; key < KeysPerCharacter; key++)
            {
                mCurrentKeys[c, key] = mBaseKeys[c, Random.Range(0, TotalKeysPerCharacter)];
            }
        }*/
        Shuffle(ref mKeyOrder);
    }
    public void ShuffleSetOrder()
    {
        Shuffle(ref mSetOrder);
    }
    public static void Shuffle<T>(ref T[] array)
    {
        int n = array.Length;
        while (n > 1)
        {
            int k = Random.Range(0, n--);
            T temp = array[n];
            array[n] = array[k];
            array[k] = temp;
        }
    }
    public static void Shuffle<T>(ref T[,] array)
    {
        int width = array.GetLength(1);
        int height = array.GetLength(0);
        while (height > 1)
        {
            int k = Random.Range(0, height--);
            T[] temp = new T[width];
            for (int i = 0; i < width; i++)
            {
                temp[i] = array[height, i];
            }
            //array[height] = array[k];
            for (int i = 0; i < width; i++)
            {
                array[height, i] = array[k, i];
            }
            //array[k] = temp;
            for (int i = 0; i < width; i++)
            {
                array[k, i] = temp[i];
            }
        }
    }
    #endregion
}
