﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif

[ExecuteAlways]
public class MeshMakerScript : MonoBehaviour {

	#if UNITY_EDITOR
	[BoolToButton("combineMesh", "Combine Mesh")]
	public bool combineMesh = false;
	[BoolToButton("", "")]
	public bool placeHolder = false;

	[BoolToButton("makePrefab", "Make Prefab")]
	public bool makePrefab = false;
	[BoolToButton("", "")]
	public bool placeHolder2 = false;

	int materialCount = 0;

	bool meshCreated = false;


    // Start is called before the first frame update
    void Start () {
        
    }

    // Update is called once per frame
    void OnValidate () {
		//combineMesh = false;
		if (combineMesh) {
			combineMesh = false;
			AdvancedMerge ();
			meshCreated = true;
			
		}
	}

	void Update () {
		//combineMesh = false;
		if (meshCreated) {
			meshCreated = false;
			if (AssetDatabase.IsValidFolder ("Assets/Models/Environment Models")) {
				AssetDatabase.CreateAsset (GetComponent<MeshFilter> ().sharedMesh, "Assets/Models/Environment Models/" + transform.name + ".asset");
				gameObject.AddComponent<ColorChanger> ();
			}


		}

		if (makePrefab) {
			//Debug.Log ("hit");
			makePrefab = false;
			if (AssetDatabase.IsValidFolder ("Assets/Resources/Environment")) {
				//Debug.Log ("We in it!");
				Object newLevelPrefab = PrefabUtility.SaveAsPrefabAsset (gameObject, "Assets/Resources/Environment/" + gameObject.name + ".prefab");
				PrefabUtility.SaveAsPrefabAssetAndConnect (gameObject, "Assets/Resources/Environment/" + gameObject.name + ".prefab", InteractionMode.AutomatedAction);
				//AssetDatabase.Refresh ();
				//EditorSceneManager.SaveScene (EditorSceneManager.GetActiveScene ());
			}
		}
	}

	public void AdvancedMerge () {
		
		// All our children (and us)
		MeshFilter[] filters = GetComponentsInChildren<MeshFilter> ();

		// All the meshes in our children (just a big list)
		List<Material> materials = new List<Material>();
		MeshRenderer[] renderers = GetComponentsInChildren<MeshRenderer> (); // <-- you can optimize this


		foreach (MeshRenderer renderer in renderers) {
			if (renderer.transform == transform)
				continue;
			Material[] localMats = renderer.sharedMaterials;
			foreach (Material localMat in localMats) {
				if (!materials.Contains (localMat)) {
					materials.Add (localMat);
				}
			}

		}

		// Each material will have a mesh for it.
		List<Mesh> submeshes = new List<Mesh>();
		foreach (Material material in materials) {
			// Make a combiner for each (sub)mesh that is mapped to the right material.
			List<CombineInstance> combiners = new List<CombineInstance> ();
			foreach (MeshFilter filter in filters) {
				if (filter.transform == transform) {
					continue;
				}

				// The filter doesn't know what materials are involved, get the renderer.
				MeshRenderer renderer = filter.GetComponent<MeshRenderer> ();  // <-- (Easy optimization is possible here, give it a try!)
				if (renderer == null) {
					Debug.LogError (filter.name + " has no MeshRenderer");
					continue;
				}

				// Let's see if their materials are the one we want right now.
				Material[] localMaterials = renderer.sharedMaterials;
				for (int materialIndex = 0; materialIndex < localMaterials.Length; materialIndex++) {
					if (localMaterials [materialIndex] != material) {
						continue;
					}
					// This submesh is the material we're looking for right now.
					CombineInstance ci = new CombineInstance();
					ci.mesh = filter.sharedMesh;
					ci.subMeshIndex = materialIndex;
					ci.transform = Matrix4x4.identity;
					combiners.Add (ci);
				}
			}
			// Flatten into a single mesh.
			Mesh mesh = new Mesh ();
			mesh.CombineMeshes (combiners.ToArray(), true);
			submeshes.Add (mesh);
		}

		// The final mesh: combine all the material-specific meshes as independent submeshes.
		List<CombineInstance> finalCombiners = new List<CombineInstance> ();
		foreach (Mesh mesh in submeshes) {
			CombineInstance ci = new CombineInstance ();
			ci.mesh = mesh;
			ci.subMeshIndex = 0;
			ci.transform = Matrix4x4.identity;
			finalCombiners.Add (ci);
		}
		Mesh finalMesh = new Mesh();
		finalMesh.CombineMeshes (finalCombiners.ToArray(), false);
		materialCount = finalMesh.subMeshCount;
		GetComponent<MeshFilter>().sharedMesh = finalMesh;


		if (!GetComponent<MeshRenderer> ()) {
			gameObject.AddComponent<MeshRenderer> ();
			GetComponent<MeshRenderer> ().sharedMaterials = materials.ToArray ();
		}

		//Debug.Log ("Final mesh has " + materials.Count + " materials.");
	}


	#endif
}
