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

public class ColorChanger : MonoBehaviour {

	[HideInInspector]
	public bool valuesAssigned = false, setColors = false;

	[HideInInspector]
	public Material colorChangeMat;

	[ColorSelect("totalVals", "objectColors", "objectTextures")]
	public int totalVals = 1;

	[HideInInspector]
	public Color[] objectColors;

	[HideInInspector]
	public Texture[] objectTextures;

	MeshRenderer rend;
	Material[] sharedMaterialsCopy;


	void OnEnable () {
		if (gameObject.activeInHierarchy) {
			ConvertMaterials ();
		}
	}

	void OnValidate () {
		if (gameObject.activeInHierarchy) {
			ConvertMaterials ();
		}
	}

	// Gathers & Converts Old Materials to the Color Changer Material
	public void ConvertMaterials () {

		// Get the Mesh Renderer or say that the object needs a mesh renderer
		if (GetComponent<MeshRenderer> ()) {
			rend = GetComponent<MeshRenderer> ();
		} else {
			Debug.LogError ("The" + gameObject.name + " has no Mesh Renderer. The ColorChanger script will not work on an object without a Mesh Renderer. Please remove this script from the GameObject.");
			return;
		}

		// Get the number of materials
		totalVals = rend.sharedMaterials.Length;

		// Make a copy of the shared materials array
		sharedMaterialsCopy = rend.sharedMaterials;

		//  Get/Set the ColorChangerMat if it's not already set (Editor Only). Don't execute the rest of the code of the colorChangeMat has not been assigned
		if (!GetColorChangerMat ()) {
			setColors = false;
			Debug.LogError ("The ColorChangeMat material could not be found in the project.");
			return;
		} else {
			setColors = true;
		}

		// Get the color value from old materials and assign them to the array copy, then to the actual materials
		if (setColors) {
			
			// Create an empty array of colors that is equal to the ammount of shared materials
			if (!valuesAssigned) {
				objectColors = GetMaterialColor (rend.sharedMaterials);
				objectTextures = GetMaterialTexture (rend.sharedMaterials);
				valuesAssigned = true;
			}

			for (int i = 0; i < rend.sharedMaterials.Length; i++) {
				if (rend.sharedMaterials[i].name != "ColorChangerMat") {
					if (colorChangeMat) {
						sharedMaterialsCopy [i] = colorChangeMat;
					}
				}
			}

			rend.sharedMaterials = sharedMaterialsCopy;
			SetMaterialValues ();
		}
	}

	Color[] GetMaterialColor (Material[] materials) {
		Color[] colors = new Color[materials.Length];
		for (int c = 0; c < materials.Length; c++) {
			colors[c] = rend.sharedMaterials [c].color;
		}
		return colors;
	}

	Texture[] GetMaterialTexture (Material[] materials) {
		Texture[] textures = new Texture[materials.Length];
		for (int t = 0; t < materials.Length; t++) {
			textures[t] = rend.sharedMaterials [t].mainTexture;
		}
		return textures;
	}

	void SetMaterialValues () {
		for (int i = 0; i < rend.sharedMaterials.Length; i++) {
			// Create a Property Block to change a material's color
			MaterialPropertyBlock propBlock = new MaterialPropertyBlock ();

			// Get the current value of the material properties
			rend.GetPropertyBlock (propBlock, i);

			// Clear the block
			propBlock.Clear();

			// Set the new color value
			propBlock.SetColor ("_Color", objectColors[i]);

			// Set the new texture value
			if (objectTextures [i]) {
				propBlock.SetTexture ("_MainTex", objectTextures [i]);
			}

			// Apply the new value
			rend.SetPropertyBlock (propBlock, i);
		}
	}

	bool GetColorChangerMat () {
	#if UNITY_EDITOR
		if (!colorChangeMat || colorChangeMat.name != "ColorChangerMat") {
			string[] assetName = AssetDatabase.FindAssets("ColorChangerMat");
			colorChangeMat = AssetDatabase.LoadAssetAtPath<Material>(AssetDatabase.GUIDToAssetPath(assetName[0]));
			if(colorChangeMat){
				return true;
			}
		} else if (colorChangeMat){
			return true;
		}
		return false;
	#else
		if (colorChangeMat && colorChangeMat.name != "ColorChangerMat") {
			colorChangeMat = null;
			return false;
		}
		return true;
	#endif
	}
}
