﻿#if UNITY_EDITOR
using UnityEditor;
#endif

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using System.Linq;
using UnityEngine.SceneManagement;

public class GameInitializer : MonoBehaviour {

	[SerializeField]
	public Generator generator;

	public bool generateLevels = true;

	List<Vector3> levelLocations;
	public List<int> levels;

	static int oldSeed;

	PhotonView view;

	#if UNITY_EDITOR
	[ContextMenu("Collect Assets")]
	void CollectAssets() {

		generator.Clear();
		generator = new Generator();

		List<string[]> myGuids = new List<string[]>();
		string[] lGuids = AssetDatabase.FindAssets("t:Prefab", new string[] { "Assets/Levels" });
		string[] hGuids = AssetDatabase.FindAssets("t:Prefab", new string[] { "Assets/Do Not Edit OR Delete/Core Prefabs/Hairstyles" });
		string[] mGuids = AssetDatabase.FindAssets("t:Material", new string[] { "Assets/Materials/Hair Materials" });
		string[] tGuids = AssetDatabase.FindAssets("t:Texture", new string[] { "Assets/Textures/Player Textures" });

		myGuids.Add(lGuids);
		myGuids.Add(hGuids);
		myGuids.Add(mGuids);
		myGuids.Add(tGuids);

		for (int i = 0; i < myGuids.Count; i++) {
			for (int j = 0; j < myGuids[i].Length; j++) {
				string myAssetPath = AssetDatabase.GUIDToAssetPath(myGuids[i][j]);

				if (i < 4)
					generator.prefabObjects[i].Add(AssetDatabase.LoadAssetAtPath<GameObject>(myAssetPath));
				else if (i == 4)
					generator.hairColors.Add(AssetDatabase.LoadAssetAtPath<Material>(myAssetPath));
				else
					generator.playerTextures.Add(AssetDatabase.LoadAssetAtPath<Texture>(myAssetPath));
			}
		}
	}

	#endif

	// Use this for initialization
	void Awake() {
		view = GetComponent<PhotonView>();
		if (CheckForAssets ()) {
			int randomSeed = GenerateSeed ();

			if (view && PhotonNetwork.IsConnected && SceneManager.GetActiveScene ().name != "Launcher") {
				SetRandomSeed (oldSeed);
				//StartCoroutine(SendRandomSeed(randomSeed));
				//PhotonGameDebugger.IncrementNumberOfMessages("seed");
				//view.RPC("SetRandomSeed", RpcTarget.OthersBuffered, randomSeed);

				//SetRandomSeed(randomSeed);
				return;
			} else if (!PhotonNetwork.IsConnected && SceneManager.GetActiveScene ().name != "Launcher") {
				SetRandomSeed (randomSeed);
			}
		}
	}
	#if UNITY_EDITOR
	void OnValidate () {
		CollectAssets ();
	}
	#endif


	public void SendRandomSeed(int randomSeed) {
		PhotonGameDebugger.IncrementNumberOfMessages("seed");
		if (!view)
			view = GetComponent<PhotonView>();
		view.RPC("SetRandomSeed", RpcTarget.OthersBuffered, randomSeed);

		SetRandomSeed(randomSeed);
	}


	[PunRPC]
	void SetRandomSeed(int randomSeed) {
		oldSeed = randomSeed;
		Random.InitState(randomSeed);

		BeginGeneratingLevels();
	}

	public static int GetOldRandomSeed() {
		return oldSeed;
	}

	public static void SetRandomToOldSeed() {
		Random.InitState(oldSeed);
	}

	public int GenerateSeed() {
		int randomSeedMilli = System.DateTime.Now.Millisecond;
		int randomSeedSecond = System.DateTime.Now.Second;
		int randomSeedMinutes = System.DateTime.Now.Minute;

		string randomSeedString = randomSeedMinutes.ToString("00") + randomSeedSecond.ToString("00") + randomSeedMilli.ToString("0000");

		return int.Parse(randomSeedString);
	}

	void GenerateLevel() {
		levelLocations = new List<Vector3>();

		for (int i = -1; i < 2; i++) {
			for (int j = -1; j < 2; j++) {
				levelLocations.Add(new Vector3(400 * i, 0, 400 * j));
			}
		}

		levels = Enumerable.Range(0, generator.levels.Count).ToList();

		int[] levelIndexes = new int[9];
		for (int k = 0; k < 9; k++) {
			int index = Random.Range(0, levels.Count);
			levelIndexes[k] = levels[index];
			levels.Remove(levels[index]);
		}

		GenerateLevelFromIndexes(levelIndexes);
	}

	void BeginGeneratingLevels() {
		if (generateLevels)
		if (SceneManager.GetActiveScene().name != "Launcher")
			GenerateLevel();

	}

	void GenerateLevelFromIndexes(int[] indexes) {
		for (int k = 0; k < 9; k++) {
			//Debug.LogError("indexes[" + k + "]: " + indexes[k]);
			GameObject level = Instantiate(generator.levels[indexes[k]], levelLocations[k], Quaternion.Euler(Vector3.zero), transform);
			//generator.levels.Remove(generator.levels[indexes[k]]);

			SetLayerAndTagRecursively(level, "Environment");
		}
		transform.position = new Vector3 (-10f, 0f, -10f);
	}

	void SetLayerAndTagRecursively(GameObject obj, string layerName) {
		int layerIndex = LayerMask.NameToLayer(layerName);
		if (null == obj) {
			return;
		}

		obj.layer = layerIndex;
		obj.tag = layerName;

		foreach (Transform child in obj.transform) {
			if (null == child || child.gameObject.layer == LayerMask.NameToLayer ("Level Editor") || child.gameObject.tag == "Wand" || child.gameObject.tag == "Potion") {
				continue;
			}
			SetLayerAndTagRecursively(child.gameObject, layerName);
		}
	}

	bool CheckForAssets() {
		if (generator.levels.Count < 9) {
			for (int i = 0; i < generator.testLevels.Count; i++) {
				generator.levels.Add (generator.testLevels [i]);
				if (generator.levels.Count == 9)
					break;
			}
			if (generator.levels.Count < 9) {
				Debug.LogError ("You need at least nine (9) levels to generate a map. Please add more levels (Prefab) to the Assets/Levels folder.");
				return false;
			}
		}
		if (generator.wands.Count < 1) {
			Debug.LogError("You need at least one (1) wand to generate a map. Please add more wands (Prefab) to the Assets/Wands folder.");
			return false;
		}
		if (generator.hairStyles.Count < 1) {
			Debug.LogError("You need at least one (1) hairstyle to generate a player. Please add more hairstyles (Prefab) to the Assets/Do Not Edit OR Delete/Core Prefabs/HairStyles folder.");
			return false;
		}
		if (generator.hairColors.Count < 1) {
			Debug.LogError("You need at least one (1) haircolor to generate a player. Please add more haircolors (Material) to the Assets/Materials/Hair Materials folder.");
			return false;
		}
		if (generator.playerTextures.Count < 1) {
			Debug.LogError("You need at least one (1) player texture to generate a player. Please add more player textures (Texture) to the Assets/Textures/PlayerTextures folder.");
			return false;
		}

		return true;
	}

	// Update is called once per frame
	void Update() {
		// might do something here to automate asset collection
	}
}


[System.Serializable]
public class Generator {
	public List<List<GameObject>> prefabObjects;
	public List<GameObject> levels, hairStyles, wands, testLevels;

	public List<Material> hairColors;
	public List<Texture> playerTextures;


	public Generator() {

		levels = new List<GameObject>();
		hairStyles = new List<GameObject>();
		wands = new List<GameObject>();
		testLevels = new List<GameObject>();

		hairColors = new List<Material>();
		playerTextures = new List<Texture>();

		prefabObjects = new List<List<GameObject>>();
		prefabObjects.Add(levels);
		prefabObjects.Add(hairStyles);
		prefabObjects.Add(wands);
		prefabObjects.Add(testLevels);

	}

	public void Clear() {
		levels.Clear();
		hairStyles.Clear();
		wands.Clear();
		testLevels.Clear();
		hairColors.Clear();
		playerTextures.Clear();
		prefabObjects.Clear();
	}
}

