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

public enum GameStateType
{
    Invalid,
    Menu,
    Lobby,
    Game,
    GameOver
}

public class GameManager : MonoBehaviour
{

    #region SINGLETON
    private static GameManager m_Instance;
    //private static bool m_IsQuitting = false;

    public static GameManager Instance
    {
        get
        {
            if (m_Instance == null)
            {
                CreateInstance();
                return null;
            }
            return m_Instance;
        }
    }

    public static void CreateInstance()
    {
        // The _preload Scene contains a GameManager GameObject, it will load
        // m_Instance is going to be setup by Awake
        if (m_Instance == null)
            SceneManager.LoadScene("_preload", LoadSceneMode.Additive);
    }

    public void Awake()
    {
        // If unity is trying to create a new gameobject with this instance, i destroy it
        if (m_Instance == null)
            m_Instance = this;

        if (m_Instance != this)
        {
            DestroyImmediate(this.gameObject);
            return;
        }

        DontDestroyOnLoad(this);
        InitGameManager();
    }

    #endregion

    public bool ShowDebugInfo = false;
    public bool IsFinalBuild = false;
    // Need to serialize it
    [SerializeField]
    public PersistantGameInfo m_PersistantGameInfo;

    public static PersistantGameInfo GetPersistantGameInfo()
    {
        return m_Instance.m_PersistantGameInfo;
    }


    private string m_MenuSceneName = "Menu";
    private string m_GameOverSceneName = "GameOver";
    private string m_LobbySceneName = "Lobby";

    private GameStateType m_CurrentStateType = GameStateType.Invalid;

    private InGameState m_InGameState = null;
    public InGameState InGameState  { get { return m_InGameState; } }
    private GameState m_CurrentGameState = null;
    public GameState CurrentGameState { get { return m_CurrentGameState; } }

    private bool m_IsPaused = false;


    public void InitGameManager()
    {
        Debug.Log("Game Manager is initialized");

        // We can activate the gamemanager from any scene
        if (SceneManager.GetActiveScene().name == m_MenuSceneName && m_CurrentStateType != GameStateType.Menu)
        {
            ChangeState(GameStateType.Menu);
        }
        else if (SceneManager.GetActiveScene().name == m_GameOverSceneName && m_CurrentStateType != GameStateType.GameOver)
        {
            ChangeState(GameStateType.GameOver);
        }
        else if (SceneManager.GetActiveScene().name == m_LobbySceneName && m_CurrentStateType != GameStateType.Lobby)
        {
            ChangeState(GameStateType.Lobby);
        }
        else
            ChangeState(GameStateType.Game);
    }

    void Start()
    {
        SceneManager.sceneLoaded += OnSceneLoaded;
    }

    void Destroy()
    {
        SceneManager.sceneLoaded -= OnSceneLoaded;
    }

    public void OnSceneLoaded(Scene scene, LoadSceneMode mode)
    {
        // Called after a Scene is loaded

        if (m_CurrentGameState != null)
            m_CurrentGameState.OnSceneLoaded(scene.name);
    }

    public void GotoMenu()
    {
        ChangeState(GameStateType.Menu);
    }

    public void GotoLobby()
    {
        ChangeState(GameStateType.Lobby);
    }

    public void GotoGameOver()
    {
        ChangeState(GameStateType.GameOver);
    }

    public void GotoGameStart()
    {
        ChangeState(GameStateType.Game);
    }

    private void ChangeState(GameStateType _newState)
    {
        if (_newState != m_CurrentStateType)
        {

            ExitState(m_CurrentStateType);

            m_CurrentStateType = _newState;
            
            EnterState(m_CurrentStateType);
        }
    }

    private void EnterState(GameStateType _state)
    {
        if (_state == GameStateType.Invalid)
            return;

        switch(_state)
        {
            case GameStateType.Menu:
                {
                    m_CurrentGameState = new MenuState();
                }
                break;

            case GameStateType.Lobby:
                {
                    m_CurrentGameState = new LobbyState();
                }
                break;

            case GameStateType.Game:
                {
                    m_InGameState = new InGameState();
                    m_CurrentGameState = m_InGameState;
                }
                break;

            case GameStateType.GameOver:
                {
                    m_CurrentGameState = new GameOverState();
                }
                break;
        }

        if (m_CurrentGameState != null)
            m_CurrentGameState.OnEnter();
    }

    private void ExitState(GameStateType _state)
    {
        if (m_InGameState != null)
            m_InGameState = null;

        if (m_CurrentGameState != null )
            m_CurrentGameState.OnExit();

        m_CurrentGameState = null;
    }

    public void FixedUpdate()
    {
        if (m_CurrentGameState != null)
            m_CurrentGameState.OnUpdate();
    }

    void OnGUI()
    {
        if (ShowDebugInfo)
            GUIDebugDisplay();
    }

    public void PauseGame()
    {
        m_IsPaused = true;
        Time.timeScale = 0.0f;
    }

    public void UnPauseGame()
    {
        m_IsPaused = false;
        Time.timeScale = 1.0f;
    }

    public void TogglePause()
    {
        m_IsPaused = !m_IsPaused;
        Time.timeScale = m_IsPaused ? 0.0f : 1.0f;
            
    }

    public void GUIDebugDisplay()
    {
        string DebugText = "";

        if ( m_CurrentGameState !=  null )
            DebugText += "CurrentState :" + m_CurrentGameState.Type.ToString() + "\r\n";
        else
            DebugText += "CurrentState : null \r\n";

        GUIContent Content = new GUIContent(DebugText);
        float h = GUI.skin.textArea.CalcHeight(Content, 400);
        GUI.TextArea(new Rect(5, Screen.height - h, 405, h), DebugText);
    }
}
