// Core Class
// This is an organizational structure that performs boot-loading and ensures that it and its components survive a scene change.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

/* *
 * I am an organizational structure.
 * I exist so that everyone can call "Core Attach(this)"
 * I am also a bootloader. I will run a customizable set of following my first update.
 * */

public class /* Shoot the */ Core : MonoBehaviour 
{
	static private Core Instance;
	private List<System.Action> bootOrder = new List<System.Action>();
	private int bootPosition = 0;
	
	private static bool firstRun = true;
	
	// isLoading will return true when we are still part way into the boot-list.
	// isLoading will return false when we have recieved DoneLoading() callbacks for each function in our boot order.
	public static bool isLoading
	{
		get
		{
			if (Instance)
			{
				if (Instance.bootPosition >= Instance.bootOrder.Count)
				{
					return false;
				}
			}
			else // No instance? No loading!
			{
				Debug.LogWarning("isLoading: Core instance does not exist. Cannot perform load.");
				return false;
			}
			return true;
		}
	}
	
	// Call Core.Attach(this) when you want to attach a gameobject to the core through the transform hierarchy.
	public static void Attach(MonoBehaviour x)
	{
		// Guarded in case the instance is null;
		if (Instance != null)
		{
			x.transform.parent = Instance.transform;
		}
	}
	
	// Call Core.Add<Type>() for when you want to attach a component (monobehaviours included) to the core.
	public static T Add<T>() where T : Component
	{
		return Instance.gameObject.AddComponent<T>();
	}
	
	// On awake, we have just instantiated the Core. Assign our Singleton instance to ourselves.
	void Awake () 
	{
		Instance = this;
	}
	
	// After awaking, we will have a gameobject and all of our typical components. We'll also exist along side all other simultaneously instantiated gameobjects in our scene.
	// It's here that we'll make outselves immune to scene-change destruction, and we'll fill our BootOrder with a list of loading functions for our components.
	// We'll also immunize the camera from scene-changes, too.
	void Start()
	{
		DontDestroyOnLoad(this.gameObject);
		//DontDestroyOnLoad(Camera.main.gameObject);
		
		bootOrder.Add (()=> GoToMainMenu());
	}
	
	// Update is called once, and only once. We know that Unity will call update after all simultaneous starts have been completed, so we can use this as a 'late init.'
	// By disabling the Core Monobehaviour, we will prevent future updates, yet, we will still be able to access the core.
	void Update () 
	{
		if (firstRun)
		{
			FirstRun();
		}
	}
	
	private void FirstRun()
	{
		//CameraOff();
		SplashScreen.SetDismissTrigger(SplashScreen.DismissTrigger.AnyKeyDoneLoading);
		//SplashScreen.AddSummonAction(CameraOn);
		//SplashScreen.AddDismissAction(CameraOn);
		SplashScreen.AddDismissAction(MainMenuManager.Enable);
		SplashScreen.Summon();
		DoneLoading();
		
		enabled = false;
		firstRun = false;
	}
	
	// This is a callback. Components that we've invoked in the BootOrder must call Core.DoneLoading(), or else the Core will not load the next item in the order.
	// And we'll all be left here waiting.
	public static void DoneLoading()
	{
		if (Instance)
		{
			if (Instance.bootPosition >= 0 && Instance.bootPosition < Instance.bootOrder.Count)
			{
				Instance.bootOrder[Instance.bootPosition]();
				Instance.bootPosition++;
			}
		}
		else
		{
			Debug.LogWarning("DoneLoading: Core instance does not exist. Cannot perform load.");
		}
	}

	/*
	// Screen blanking functions.
	public static void CameraOff()
	{
		if (Camera.main)
		{
			LayerMask m = 1 << Instance.gameObject.layer;
			Camera.main.cullingMask = m;
			Camera.main.clearFlags = CameraClearFlags.Color;
		}
		else
		{
			Debug.LogWarning("CameraOff: No main camera present: Cannot disable camera.");
		}
	}
	
	public static void CameraOn()
	{
		if (Camera.main)
		{
			Camera.main.cullingMask = -1;
			Camera.main.clearFlags = CameraClearFlags.Skybox;
		}
		else
		{
			Debug.LogWarning("CameraOn: No main camera present: Cannot enable camera.");
		}
	}
	*/
	
	public static void GoToMainMenu()
	{
		GamesceneManager.LoadMenu(0);
	}
}
