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

public class GameManager : MonoBehaviour
{
    private static GameManager s_Instance;
    public static GameManager Instance
    {
        get
        {
            if (s_Instance == null)
            {
                GameObject go = Instantiate(Resources.Load("Prefabs/_GameManager")) as GameObject;
                go.name = "_GameManager";
            }
            return s_Instance;
        }
    }

    // Game management
    private bool m_InGame;
    private bool m_Intro;

    // Characters
    // -> Hero
    private Character m_Hero;
    private Transform m_HeroTransform;
    public Transform HeroTransform
    {
        get { return m_HeroTransform; }
    }
    public bool PlayerCanMove
    {
        set 
        {
            m_Hero.CharacterCanMove(value);
        }
    }
    // -> Enemies
    private List<Character> m_Enemies;

    // Progress
    private LevelSettings.LevelName m_CurrentLevel;
    private Level m_Level;
    private CheckPoint m_CurrentCheckPoint;
    private CheckPoint m_LastCheckPoint;

	void Awake()
    {
        DontDestroyOnLoad(gameObject);
        s_Instance = this;
        m_InGame = false;

        if (Application.loadedLevelName == "MainMenu")
        {
            
        }
        else
        {
            // Check for the current level
            string[] lvlNames = Enum.GetNames(typeof(LevelSettings.LevelName));
            for (int i = 0; i < lvlNames.Length; ++i)
            {
                if (lvlNames[i] == Application.loadedLevelName)
                {
                    m_CurrentLevel = (LevelSettings.LevelName)i;
                }
            }
            Debug.Log("Current level : " + m_CurrentLevel.ToString());
            if (m_CurrentLevel.ToString() == "Intro") m_Intro = true;
            else m_Intro = false;

            StartCoroutine("C_InitializeLevel");
        }
	}

    private IEnumerator C_InitializeLevel()
    {
        // Wait for loading
        while (Application.isLoadingLevel)
        {
            yield return 0;
        }

        // TODO : Get progress in the current level

        // TODO : Get and initialize the level
        m_Level = (FindObjectOfType(typeof(Level)) as Level);
        m_Level.SetStoryProgress(0);

        if (!m_Intro)
        {
            m_Hero = GameObject.Find("Hero").GetComponent<Hero>();
            m_HeroTransform = m_Hero.m_CharacterModel;

            Character[] tmpArray = FindObjectsOfType(typeof(Enemy)) as Character[];
            m_Enemies = new List<Character>();
            foreach (Character enemy in tmpArray)
            {
                m_Enemies.Add(enemy);
            }
        }
        m_InGame = true;
    }
	
	void Update()
    {
        if (m_InGame)
        {
            m_Level.UpdateLevel();
            if (!m_Intro)
            {
                if(m_Hero != null) m_Hero.UpdateCharacter();
                if (m_Enemies != null && m_Enemies.Count > 0)
                {
                    foreach (Character enemy in m_Enemies)
                    {
                        enemy.UpdateCharacter();
                    }
                }
            }
        }
        else
        {
            // TODO : Menu
        }
    }

    #region Events
    public void NewCheckPoint(CheckPoint cp)
    {
        //Debug.Log("new checkpoint");

        if (cp == m_CurrentCheckPoint)
        {
            //Debug.Log("Actually it's the same checkpoint...");
            return;
        }

        if (m_CurrentCheckPoint == null || cp.Order > m_CurrentCheckPoint.Order)
        {
            m_LastCheckPoint = cp;
        }

        if (m_CurrentCheckPoint != null)
        {
            m_CurrentCheckPoint.SaveProgress();
        }

        m_CurrentCheckPoint = cp;
        m_CurrentCheckPoint.SaveProgress();
    }

    public void NextLevel()
    {
        if (m_Intro) m_Intro = false;
        m_InGame = false;
        m_CurrentLevel++;
        // Check if this is the last one
        if ((int)m_CurrentLevel == Enum.GetNames(typeof(LevelSettings.LevelName)).Length)
        {
            Debug.Log("Game finished");
            Application.LoadLevel("End");
            return;
        }

        Application.LoadLevel(m_CurrentLevel.ToString());
        StartCoroutine("C_InitializeLevel");
    }

    public void Lost()
    {
        m_InGame = false;
        m_Level.Lost();
        StartCoroutine("C_Lost");
    }

    private IEnumerator C_Lost()
    {
        yield return new WaitForSeconds(0.5f);
        // Fade in
        Fade.Instance.In();

        yield return new WaitForSeconds(1f);
        // The hero come back to the last checkpoint
        m_Hero.Spawn(m_CurrentCheckPoint.Position);
        m_Level.SetStoryProgress(m_LastCheckPoint.StoryStep);
        m_Level.LoadProgress();

        yield return new WaitForSeconds(0.5f);
        m_InGame = true;
        yield return new WaitForSeconds(0.5f);
        // Fade out
        Fade.Instance.Out();
    }
    #endregion
}