// Gamescene Manager Class
// Emulates a very simple gamestate system by swapping scenes.
// 
// It's probably a bad idea to make this a monobehaviour. A future version should make this a static singleton.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class GamesceneManager : MonoBehaviour 
{
	// A game scene manager is an attempt at enforcing gamestate management - like behavior into a unity project.
	// Instead of gamestates, we're going to have scenes. Scenes will be inserted additively over one another in order to populate the gameworld with control objects and menu things.
	// We'll also abuse the ability to tell gameobjects not to destroy themselves when levels are loaded. We'll use that to keep our persistent objects around after loading a "clear" scene.
	// Because it's a pain to track which objects come into existence when a level is loaded, we're just going to pop gamestates with a by paying one white, three colorless and dropping an armageddon.
	// I had an excellent top-deck armageddon once.
	public int  IdxCore		= 0;
	public int  IdxClear 	= 1;
	public int  IdxMenu		= 2;//Depreciate
	public int[]IdxMenus	= new int[0];
	public int[]IdxModes 	= new int[0];
	public int[]IdxLevels 	= new int[0];
	public int[]IdxDecorate = new int[0];
	
	private Queue<Actions> actionQueue = new Queue<Actions>();
	private Queue<int> parameterQueue = new Queue<int>();
	
	public enum Actions
	{
		LoadMode,
		LoadLevel
	}
	
	private bool isLoading = false;
		

	
	static private GamesceneManager Instance = null;
	static public GamesceneManager GetInstance()
	{
		// An instance is set on Awake. We should never need to test to see if an Instance exists or not.
		return Instance;
	}
	
	void Awake ()
	{
		Instance = this;
	}

	void Start () 
	{
		Core.Attach(this);
	}
	
	// Update is called once per frame
	void Update () 
	{
		if (isLoading)
		{
			LoadingScreen.EndLoad();
			isLoading = false;
		}
		
		if (actionQueue.Count > 0 && parameterQueue.Count > 0)
		{
			Actions a = actionQueue.Dequeue();
			switch(a)
			{
			case Actions.LoadLevel:
				//print ("Load Level");
				GamesceneManager.LoadLevel(parameterQueue.Dequeue());
				//GameplayController.Init(); 	// This is a necessary evil to ensure that the GameplayManager performs necessary game-start functions on game start. The current system has levels and modes loading in different frames.
				break;
			case Actions.LoadMode:
				//print ("Load Mode");
				GamesceneManager.LoadMode(parameterQueue.Dequeue());
				break;
			default:
				//print ("Default");
				break;
			}
		}
		else if (actionQueue.Count != parameterQueue.Count)
		{
			//print ("Oops");
			actionQueue.Clear();
			parameterQueue.Clear();
		}
	}
	
	#region Scene Loaders
	static public void LoadMode(int i)
	{
		LoadingScreen.StartLoad();
		Instance.enabled = true;
		if (i < 0 || i >= Instance.IdxModes.Length)
		{
			return;
		}
		Application.LoadLevel(Instance.IdxModes[i]);
	}
	
	static public void LoadLevel(int i)
	{
		LoadingScreen.StartLoad();
		Instance.isLoading = true;
		if (i < 0 || i >= Instance.IdxLevels.Length)
		{
			return;
		}
		Application.LoadLevel(Instance.IdxLevels[i]);
	}
	
	//Depreciate
	static public void LoadMenu()
	{
		LoadingScreen.StartLoad();
		Instance.isLoading = true;
		Application.LoadLevel(Instance.IdxMenu);
	}
	//Depreciate
	
	static public void LoadMenu(int i)
	{
		LoadingScreen.StartLoad();
		Instance.isLoading = true;
		Application.LoadLevel(Instance.IdxMenus[i]);
	}
	
	static public void LoadCore()
	{
		LoadingScreen.StartLoad();
		Instance.isLoading = true;
		Application.LoadLevel(Instance.IdxCore);
	}
	
	static public void Clear()
	{
		LoadingScreen.StartLoad();
		Instance.isLoading = true;
		Application.LoadLevel(Instance.IdxClear);
	}
	
	static public void ScheduleLoad(Actions action, int parameter)
	{
		Instance.actionQueue.Enqueue(action);
		Instance.parameterQueue.Enqueue(parameter);
	}
	#endregion
}
