using System;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
//using UnityEngine.Analytics;
using UnityEngine.SceneManagement;

public class GameController : MonoBehaviour {

    public static GameController Instance;

    public Transform PlayerStartPrefab;
    public float Volume=1.0f;
	public AudioClip WinSong;
	public AudioClip LoseSong;
	private AudioSource audioSrc;

	public string DEBUG;

	private bool levelIsLoading = false;
	private float levelLoadingUntil = 0;
	
	public bool IsGameShuttingDown=false;

	public Transform Player;
	private ActorStatus pstat;
    private LevelGenerator generator;

    public bool DebugKeysAllowed = false;

	private enum GameState
	{
		MenuTitleScreen,
		LevelScreen,
		Running,
		SummaryScreen,
//-		TutorialScreen,
//-        MatchStart,
//-        OpenStart,
        GameOver,
        BeatGame
	}
	private GameState state;
	private float lastSwitchTime;

	public int WaveNum=0;
    public float LastWaveTime = -999;
    public int Sector = 1;
	private bool LevelFinished=false;

    private float gameClockStart;
    private bool onTitleScreen = true; // TODO unfortunately i bundled some init in the title screen that's needed for restarts, but this is in need of a refactor

	void Awake() {
        Instance = this;
    }

    void Start () 
	{
        Cursor.visible = false;
        Cursor.lockState = CursorLockMode.Locked;
        audioSrc = gameObject.AddComponent<AudioSource>();
        generator = GetComponent<LevelGenerator>();

        EnterState(GameState.MenuTitleScreen);
    }

    void OnApplicationQuit() { 
		Debug.Log ("GameController.OnApplicationQuit");
		IsGameShuttingDown = true; 
	}
	
	public bool isGameRunning()
	{
        return (levelLoadingUntil < Time.time) && state == GameState.Running;//- || state == GameState.MenuTitleScreen || (state == GameState.SummaryScreen && Victory) || state == GameState.MatchStart || state == GameState.OpenStart;
	}

    public void WinLevel()
    {
        LevelFinished = true;
    }

    public void FoundTheAmulet()
    {
        EnterState(GameState.BeatGame);
    }

    private void SkipToLevel(int l)
    {
        WaveNum = 1;
        Sector = l;
        EnterState(GameState.LevelScreen);
    }

    private bool CheckDebugKeys()
    {
        if (!DebugKeysAllowed)
            return false;

        if(Input.GetKeyDown(KeyCode.Alpha1))
        {
            SkipToLevel(1);
            return true;
        }
        else if (Input.GetKeyDown(KeyCode.Alpha2))
        {
            SkipToLevel(2);
            return true;
        }
        else if (Input.GetKeyDown(KeyCode.Alpha3))
        {
            SkipToLevel(3);
            return true;
        }
        else if (Input.GetKeyDown(KeyCode.Alpha4))
        {
            SkipToLevel(4);
            return true;
        }
        else if (Input.GetKeyDown(KeyCode.Alpha5))
        {
            SkipToLevel(5);
            return true;
        }
        else if (Input.GetKeyDown(KeyCode.Alpha6))
        {
            SkipToLevel(6);
            return true;
        }
        else if (Input.GetKeyDown(KeyCode.Alpha7))
        {
            SkipToLevel(7);
            return true;
        }
        else if (Input.GetKeyDown(KeyCode.Alpha8))
        {
            SkipToLevel(8);
            return true;
        }
        else if (Input.GetKeyDown(KeyCode.Alpha9))
        {
            SkipToLevel(9);
            return true;
        }
        else if (Input.GetKeyDown(KeyCode.Alpha0))
        {
            SkipToLevel(10);
            return true;
        }
        else if (Input.GetKeyDown(KeyCode.Minus))
        {
            SkipToLevel(11);
            return true;
        }
        else if (Input.GetKeyDown(KeyCode.Equals))
        {
            SkipToLevel(12);
            return true;
        }
        else if (Input.GetKeyDown(KeyCode.Backspace))
        {
            SkipToLevel(13);
            return true;
        }
        else if (Input.GetKeyDown(KeyCode.Home))
        {
            SkipToLevel(14);
            return true;
        }

        return false;
    }

    private void InstantiateNewPlayer()
    {
        if(Player != null)
        {
            GameObject.DestroyImmediate(Player.gameObject);
        }
        Debug.Log("GameController Placing new player");
        Player = GameObject.Instantiate(PlayerStartPrefab);
        if(Sector == 5 && WaveNum == 3)
            Player.position = new Vector3(0, -4,0);
        else
            Player.position = Vector3.zero;
        Player.eulerAngles = new Vector3(0, 0, 90);
        Player.name = "Player";
        pstat = Player.GetComponentInChildren<ActorStatus>();
    }

	void Update () 
	{
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            /*
            Analytics.CustomEvent("QuitGame", new Dictionary<string, object>
                          {
                            { "LevelNum", LevelNum },
                            { "Gametime", Time.realtimeSinceStartup}
                          });
            */
            Application.Quit();
        }
        
        if (CheckDebugKeys())
            return;

       /* if(Input.GetKeyDown(KeyCode.S))
        {
            Sector++;
            EnterState(GameState.LevelScreen);
            return;
        }*/

		switch(state)
		{
		case GameState.MenuTitleScreen:
            if (Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.Space) || !onTitleScreen)
			{
                onTitleScreen = false;
                InstantiateNewPlayer();
                WaveNum = 1;
                Sector = 1;
                pstat.Health = pstat.MaxHealth;
                EnterState(GameState.LevelScreen);                
			}
			break;

		case GameState.LevelScreen:
			if(Input.GetMouseButtonDown(0))
			{
				levelLoadingUntil = Time.time + 5f;				
                levelIsLoading = true;
                //if(LevelNum == 1)
                //    SceneManager.LoadScene("EntryRoom");
                Debug.Log("Loading PlayScene for Sector " + Sector);
                
                SceneManager.LoadScene("PlayScene");
                Player.position = Vector3.zero;
				LevelFinished = false;
//                WaveNum = 1;                
				EnterState(GameState.Running);
			}
			break;

		case GameState.Running:
            if (levelIsLoading)
                break;

			if(pstat.Health <= 0)
			{
				Debug.Log ("No health left, player lost");
                /*
                     Analytics.CustomEvent("gameOver", new Dictionary<string, object>
                          {
                            { "LevelNum", LevelNum },
                            { "Gametime", Time.realtimeSinceStartup},
                            { "Sector", Sector},
                            { "Wave", WaveNum}
                          });
                     */
                EnterState (GameState.GameOver);
			}
			else
			{

                // TODO add condition for finishing the level!
                GameObject targ = GameObject.FindGameObjectWithTag("Target");
                if (targ == null)// || Input.GetKeyDown(KeyCode.V))
                    LevelFinished = true;

				if(LevelFinished)
				{
                    WaveNum++;
                    if(WinSong != null)
                        iTween.Stab(gameObject, WinSong, 0);
                    if(WaveNum == 4)
                    {
                        Sector++;

                        if (Sector >= 6)
                        {
                            LastWaveTime = -999f;
                            EnterState(GameState.BeatGame);
                        }
                        else
                        {
                            WaveNum = 1;
                            EnterState(GameState.LevelScreen);
                            LastWaveTime = -999f;
                        }

                        /*
                     Analytics.CustomEvent("sectorWon", new Dictionary<string, object>
                          {
                            { "LevelNum", LevelNum },
                            { "Gametime", Time.realtimeSinceStartup},
                            { "Sector", Sector}
                          });
                     */
                    }
                    else
                    {
                        LevelFinished = false;
                        generator.GenerateWave(false);
                        LastWaveTime = Time.time;
                        /*
                     Analytics.CustomEvent("waveWon", new Dictionary<string, object>
                          {
                            { "LevelNum", LevelNum },
                            { "Gametime", Time.realtimeSinceStartup},
                            { "Sector", Sector},
                            { "Wave", WaveNum}
                          });
                     */
                    }

                    
                }
			}
			break;

        case GameState.GameOver:
            // TODO make the game over screen fun somehow, maybe move "game over" into game space, not sep screen
            if (Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.Space))
            {
                pstat.Health = 1;
                EnterState(GameState.LevelScreen);
            }
            break;

		case GameState.BeatGame:
            if (Time.fixedTime-lastSwitchTime>2f && ( Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.Space)))
			{
				EnterState(GameState.MenuTitleScreen);
			}
			break;

		}
	}
	
	void OnLevelWasLoaded()
	{
		levelIsLoading = false;
		if(WaveNum>1)
			levelLoadingUntil = Time.time + 0.08f;
		else
			levelLoadingUntil = Time.time;

        if(state == GameState.Running)
        {
            LastWaveTime = Time.time;
            generator.GenerateWave(true);
        }
	}

	private void EnterState(GameState newState)
	{
		lastSwitchTime = Time.time;
		GameState oldState = state;
		state = newState;

		Debug.Log ("GameController Entering State " + state + " from " + oldState);

		switch(state)
		{
		case GameState.MenuTitleScreen:
            /*Analytics.CustomEvent("newGame", new Dictionary<string, object>
                        {
                        { "Gametime", Time.realtimeSinceStartup}
                        });
                */
			break;
		case GameState.LevelScreen:
            levelLoadingUntil = Time.time + 5f;
            levelIsLoading = true;
            Debug.Log("GameController Loading SectorScene title, for Sector " + Sector);
            SceneManager.LoadScene("SectorScene");
			break;
		case GameState.Running:
			Player.gameObject.SetActive(true);			
			break;
        case GameState.GameOver:
            //if (LoseSong != null)
            //    iTween.Stab(gameObject, LoseSong, 0);

            levelLoadingUntil = Time.time + 5f;
            levelIsLoading = true;
            Debug.Log("GameController Loading GameOver scene");
            SceneManager.LoadScene("99-GameOver");
            break;
        case GameState.BeatGame:
            levelLoadingUntil = Time.time + 5f; // 5 seconds is much longer than level load time
            SceneManager.LoadScene("BeatGame");
            break;
		}

	}

}
