﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditorInternal;
using System.IO;

namespace RapidIconUIC
{
	[Serializable]
	public class IconEditor
	{
		RapidIconWindow window;
		public AssetGrid assetGrid;
		int currentIconIndex;
		Icon currentIcon;
		bool resizeChk;
		Vector2 previewScrollPos, controlsScrollPos;
		public Vector2Int renderResolution, renderSize;
		GUIStyle renderStyle, scrollStyle;
		int zoomScaleIndex;
		float[] zoomScales = new float[] { 0.25f, 0.5f, 0.75f, 1f, 1.25f, 1.5f, 2f, 3f, 1f };
		string[] zoomScalesStrings = new string[] { "25%", "50%", "75%", "100%", "125%", "150%", "200%", "300%", "Scale to Fit ( num %)" };
		public int resMultiplyerIndex;
		public float[] resMultiplyers = new float[] { 0.25f, 0.5f, 1f };
		string[] resMultiplyersStrings = new string[] { "Quarter", "Half", "Full" };
		bool setAlphaIsTransparency;
		Texture2D previewBackgroundImage, scrollAreaBackgroundImage, scaleLinkOnImage, scaleLinkOffImage, separatorTex;
		Vector2 previewAreaSize;
		int zoomFitByWidthHeight; //0: height, 1: width
		int tab;
		string[] tabNames = new string[] {"Object", "Camera", "Lighting", "Post-Processing", "Export" };
		bool updateFlag;
		bool linkScale;
		bool replaceAll;
		float sepWidth;
		string lastPresetPath;

		MaterialEditor materialEditor;
		Material mat;
		ReorderableList reorderableList;

		DraggableSeparator previewDraggableSeparator;

		public IconEditor(AssetGrid grid, RapidIconWindow w)
		{
			assetGrid = grid;
			renderResolution = new Vector2Int(256, 256);
			renderSize = new Vector2Int(256, 256);
			renderStyle = new GUIStyle();
			renderStyle.stretchWidth = true;
			renderStyle.stretchHeight = true;
			renderStyle.stretchHeight = true;
			renderStyle.stretchWidth = true;
			zoomScaleIndex = 8;
			CheckAndSetWindow(w);
			resMultiplyerIndex = 2;

			scrollAreaBackgroundImage = Utils.CreateColourTexture(4, 4, new Color32(50, 50, 50, 255));

			if (EditorGUIUtility.isProSkin)
				separatorTex = Utils.CreateColourTexture(2, 2, new Color32(31, 31, 31, 255));
			else
				separatorTex = Utils.CreateColourTexture(2, 2, new Color32(153, 153, 153, 255));
			previewBackgroundImage = (Texture2D)AssetDatabase.LoadMainAssetAtPath(assetGrid.rapidIconRootFolder + "Editor/UI/previewGrid.png");
			scaleLinkOnImage = (Texture2D)AssetDatabase.LoadMainAssetAtPath(assetGrid.rapidIconRootFolder + "Editor/UI/linkOn.png");
			scaleLinkOffImage = (Texture2D)AssetDatabase.LoadMainAssetAtPath(assetGrid.rapidIconRootFolder + "Editor/UI/linkOff.png");
			previewDraggableSeparator = new DraggableSeparator(SeparatorTypes.Horizontal);
			linkScale = true;
			replaceAll = false;
			mat = new Material(Shader.Find("RapidIcon/ObjectRender"));
			materialEditor = (MaterialEditor)Editor.CreateEditor(mat);

			List<Material> blankList = new List<Material>();
			reorderableList = new ReorderableList(blankList, typeof(Material), true, true, true, true);
			reorderableList.drawElementCallback = DrawListItems;
			reorderableList.drawHeaderCallback = DrawHeader;
			reorderableList.onSelectCallback = SelectShader;
			reorderableList.onAddCallback = AddShader;
			reorderableList.onRemoveCallback = RemoveShader;
			reorderableList.onReorderCallback = ShadersReorded;

			Undo.undoRedoPerformed += OnUndo;
		}

		public void Draw(float width, RapidIconWindow w)
		{
			CheckAndSetWindow(w);

			if (assetGrid.selectedIcons.Count > 0)
			{
				currentIconIndex = Mathf.Clamp(currentIconIndex, 0, assetGrid.selectedIcons.Count - 1);
				currentIcon = assetGrid.selectedIcons[currentIconIndex];

				if (currentIcon.assetObject == null)
				{
					currentIcon.deleted = true;
					assetGrid.selectedIcons.Remove(currentIcon);

					if (assetGrid.selectedIcons.Count > 0)
					{
						if (currentIconIndex > assetGrid.selectedIcons.Count - 1)
							currentIconIndex = assetGrid.selectedIcons.Count - 1;

						currentIcon = assetGrid.selectedIcons[currentIconIndex];
					}
					else
						return;
				}

				//Create an area to prevent buggy behaviour when moving left separator
				Rect r = new Rect(window.rightSeparator.rect);
				r.width = width;
				GUILayout.BeginArea(r);

				GUILayout.BeginVertical();
				GUI.enabled = assetGrid.selectedIcons.Count > 0;

				if (updateFlag)
				{
					UpdateIcon(currentIcon);
					updateFlag = false;
				}
				CheckCurrentIconRender();

				DrawPreview();
				GUILayout.Space(2);
				DrawPreviewResAndZoom();
				previewDraggableSeparator.Draw(100, window.position.height - 100, window);

				GUILayout.Space(8);

				DrawIconSelecter();
				tab = GUILayout.Toolbar(tab, tabNames);

				sepWidth = width - 50;
				DrawTabs();
				GUI.enabled = true;
				GUILayout.EndVertical();
				GUILayout.EndArea();

			}
			else if (Event.current.type == EventType.Layout || Event.current.type == EventType.Repaint)
			{
				GUILayout.BeginVertical();
				GUILayout.FlexibleSpace();
				GUILayout.BeginHorizontal();
				GUILayout.FlexibleSpace();
				GUILayout.Label("No Icons Selected");
				GUILayout.FlexibleSpace();
				GUILayout.EndHorizontal();
				GUILayout.FlexibleSpace();
				GUILayout.EndVertical();
			}
		}

		public void SaveData()
		{
			previewDraggableSeparator.SaveData("RapidIconSepPosPreview");

			IconData iconData = new IconData();

			foreach (KeyValuePair<UnityEngine.Object, Icon> icon in assetGrid.objectIcons)
			{
				if (icon.Value.saveData)
					iconData.icons.Add(icon.Value);
			}

			Utils.SaveIconData(iconData);

			EditorPrefs.SetInt(PlayerSettings.productName + "RapidIconPreviewResIdx", resMultiplyerIndex);
			EditorPrefs.SetInt(PlayerSettings.productName + "RapidIconPreviewZoomIdx", zoomScaleIndex);
			EditorPrefs.SetInt(PlayerSettings.productName + "RapidIconEditorTab", tab);
		}

		public void LoadData()
		{
			IconData iconData = new IconData();
			iconData = Utils.LoadIconData();

			assetGrid.objectIcons = new Dictionary<UnityEngine.Object, Icon>();
			if (iconData != null)
			{
				foreach (Icon icon in iconData.icons)
				{
					if (icon.assetObject != null)
						assetGrid.objectIcons.Add(icon.assetObject, icon);
				}
			}

			previewDraggableSeparator.LoadData("RapidIconSepPosPreview", 400);

			resMultiplyerIndex = EditorPrefs.GetInt(PlayerSettings.productName + "RapidIconPreviewResIdx", -1);
			zoomScaleIndex = EditorPrefs.GetInt(PlayerSettings.productName + "RapidIconPreviewZoomIdx", -1);

			if (resMultiplyerIndex == -1)
				resMultiplyerIndex = 2;

			if (zoomScaleIndex == -1)
				zoomScaleIndex = 8;

			tab = EditorPrefs.GetInt(PlayerSettings.productName + "RapidIconEditorTab");
		}

		void OnUndo()
		{
			updateFlag = true;

			foreach (Icon icon in assetGrid.objectIcons.Values)
				icon.LoadMatInfo();
		}

		void CheckAndSetWindow(RapidIconWindow w)
		{
			if (!window)
				window = w;
		}

		void ExportIcon(Icon icon, bool inBatchExport)
		{
			if (!Directory.Exists(icon.exportFolderPath))
				Directory.CreateDirectory(icon.exportFolderPath);

			string fileName = icon.exportFolderPath + icon.assetName;
			int extensionPos = fileName.LastIndexOf('.');
			fileName = fileName.Substring(0, extensionPos);

			if (System.IO.File.Exists(fileName + ".png") && !replaceAll)
			{
				int result = 1;

				if (inBatchExport)
					result = EditorUtility.DisplayDialogComplex("Replace File?", fileName + ".png already exists, do you want to replace it?", "Replace", "Skip", "Replace All");
				else
					result = EditorUtility.DisplayDialog("Replace File?", fileName + ".png already exists, do you want to replace it?", "Replace", "Cancel") ? 0 : 1;

				if (result == 1)
					return;
				else if(result == 2)
				{
					replaceAll = true;
				}
			}

			if(AssetDatabase.IsValidFolder(icon.exportFolderPath))
				AssetDatabase.DeleteAsset(fileName + ".png");

			Texture2D exportRender = Utils.RenderIcon(icon, icon.exportResolution.x, icon.exportResolution.y);
			byte[] bytes = exportRender.EncodeToPNG();

			File.WriteAllBytes(fileName + ".png", bytes);
		}

		void FinishExportIcon(List<Icon> icons)
		{
			AssetDatabase.Refresh();
			foreach (Icon icon in icons)
			{
				string fileName = icon.exportFolderPath + icon.assetName;
				int extensionPos = fileName.LastIndexOf('.');
				fileName = fileName.Substring(0, extensionPos);

				if (AssetDatabase.IsValidFolder(icon.exportFolderPath.Substring(0, icon.exportFolderPath.Length - 1)))
				{
					TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(fileName + ".png");
					textureImporter.alphaIsTransparency = true;
					textureImporter.npotScale = TextureImporterNPOTScale.None;
					textureImporter.textureCompression = TextureImporterCompression.Uncompressed;
					textureImporter.SaveAndReimport();
				}
			}
			AssetDatabase.Refresh();
		}
		void FinishExportIcon(Icon icon)
		{
			AssetDatabase.Refresh();
			string fileName = icon.exportFolderPath + icon.assetName;
			int extensionPos = fileName.LastIndexOf('.');
			fileName = fileName.Substring(0, extensionPos);

			if (AssetDatabase.IsValidFolder(icon.exportFolderPath.Substring(0, icon.exportFolderPath.Length - 1)))
			{
				TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(fileName + ".png");
				textureImporter.alphaIsTransparency = true;
				textureImporter.npotScale = TextureImporterNPOTScale.None;
				textureImporter.textureCompression = TextureImporterCompression.Uncompressed;
				textureImporter.SaveAndReimport();
			}
			AssetDatabase.Refresh();
		}


		void UpdateIcon(Icon icon)
		{
			renderResolution = Utils.MutiplyVector2IntByFloat(currentIcon.exportResolution, resMultiplyers[resMultiplyerIndex]);
			icon.Update(renderResolution, new Vector2Int(128, (int)(((float)renderResolution.y / (float)renderResolution.x) * 128)));
		}

		void DrawIconSelecter()
		{
			GUILayout.BeginHorizontal();
			if (GUILayout.Button("<", GUILayout.Width(100)) && currentIconIndex > 0)
				currentIconIndex--;

			int idx = 0;
			string[] iconNames = new string[assetGrid.selectedIcons.Count];
			foreach (Icon icon in assetGrid.selectedIcons)
				iconNames[idx++] = (icon.assetName);

			currentIconIndex = EditorGUILayout.Popup(currentIconIndex, iconNames);
			if (GUILayout.Button(">", GUILayout.Width(100)) && currentIconIndex < assetGrid.selectedIcons.Count - 1)
				currentIconIndex++;
			GUILayout.EndHorizontal();

			// Placeholder
			/*GUILayout.BeginHorizontal();
			if (GUILayout.Button("<") && currentIconIndex > 0)
				currentIconIndex--;
			GUILayout.Label(currentIconIndex + ": " + currentIcon.assetShortenedName);
			if (GUILayout.Button(">") && currentIconIndex < assetGrid.selectedIcons.Count - 1)
				currentIconIndex++;
			GUILayout.EndHorizontal();*/
		}

		void DrawPreview()
		{
			if(scrollStyle == null)
			{
				scrollStyle = new GUIStyle(GUI.skin.scrollView);
				scrollStyle.margin.left = 1;
				scrollStyle.normal.background = scrollAreaBackgroundImage;
			}

			previewScrollPos = GUILayout.BeginScrollView(previewScrollPos, scrollStyle, GUILayout.Height(previewDraggableSeparator.value));
			GUILayout.FlexibleSpace();
			GUILayout.BeginHorizontal();
			GUILayout.FlexibleSpace();
			renderStyle.normal.background = currentIcon.fullRender;
			renderStyle.fixedHeight = renderSize.y - 12;
			renderStyle.fixedWidth = renderSize.x - 12;
			Rect renderRect = GUILayoutUtility.GetRect(renderSize.x, renderSize.y);
			renderRect.size -= new Vector2(12, 12);
			renderRect.center += new Vector2(6, 6);
			GUI.DrawTextureWithTexCoords(renderRect, previewBackgroundImage, new Rect(0, 0, renderRect.width / 32, renderRect.height / 32));
			GUI.SelectionGrid(renderRect, 0, new GUIContent[] { new GUIContent("") }, 1, renderStyle);
			GUILayout.FlexibleSpace();
			GUILayout.EndHorizontal();
			GUILayout.FlexibleSpace();
			GUILayout.EndScrollView();
			if (Event.current.type == EventType.Repaint)
			{
				Rect r = GUILayoutUtility.GetLastRect();
				previewAreaSize = r.size;
				Vector2 delta = currentIcon.exportResolution - r.size;
				delta.x /= currentIcon.exportResolution.x;
				delta.y /= currentIcon.exportResolution.y;
				if (delta.x > 0 && delta.y > 0)
				{
					if (Mathf.Abs(delta.x) < Mathf.Abs(delta.y))
						zoomFitByWidthHeight = 0;
					else
						zoomFitByWidthHeight = 1;
				}
				else if (delta.x <= 0 && delta.y <= 0)
				{
					if (Mathf.Abs(delta.x) < Mathf.Abs(delta.y))
						zoomFitByWidthHeight = 1;
					else
						zoomFitByWidthHeight = 0;
				}
				else if (delta.y > 0)
					zoomFitByWidthHeight = 0;
				else if (delta.x > 0)
					zoomFitByWidthHeight = 1;
			}
		}

		void DrawPreviewResAndZoom()
		{
			EditorGUI.BeginChangeCheck();

			GUILayout.BeginHorizontal();
			GUILayout.FlexibleSpace();

			switch (zoomFitByWidthHeight)
			{
				case 0:
					zoomScales[8] = previewAreaSize.y / (float)(currentIcon.exportResolution.y);
					break;
				case 1:
					zoomScales[8] = previewAreaSize.x / (float)(currentIcon.exportResolution.x);
					break;
			}
			if (assetGrid.selectedIcons.Count == 0)
				zoomScales[8] = 1;
			string s = "Scale to Fit (" + (100f * (float)zoomScales[8]).ToString("f1") + "%)";
			zoomScalesStrings[8] = s;

			GUILayout.Label("Preview Resolution", GUILayout.Width(115));
			resMultiplyerIndex = EditorGUILayout.Popup(resMultiplyerIndex, resMultiplyersStrings, GUILayout.Width(70));
			renderResolution = Utils.MutiplyVector2IntByFloat(currentIcon.exportResolution, resMultiplyers[resMultiplyerIndex]);

			if (EditorGUI.EndChangeCheck())
			{
				currentIcon = assetGrid.selectedIcons[currentIconIndex];
				if (currentIcon != null)
				{
					updateFlag = true;
				}
			}

			GUILayout.Space(32);

			GUILayout.Label("Zoom", GUILayout.Width(40));
			zoomScaleIndex = EditorGUILayout.Popup(zoomScaleIndex, zoomScalesStrings, GUILayout.Width(150));
			renderSize = Utils.MutiplyVector2IntByFloat(currentIcon.exportResolution, zoomScales[zoomScaleIndex]);
			GUILayout.EndHorizontal();
		}

		void CheckCurrentIconRender()
		{
			if (!currentIcon.fullRender)
			{
				renderResolution = Utils.MutiplyVector2IntByFloat(currentIcon.exportResolution, resMultiplyers[resMultiplyerIndex]);
				currentIcon.fullRender = Utils.RenderIcon(currentIcon, renderResolution.x, renderResolution.y, FilterMode.Point);
				currentIcon.fullRender.hideFlags = HideFlags.DontSave;
			}
		}

		void DrawTabs()
		{
			controlsScrollPos = GUILayout.BeginScrollView(controlsScrollPos, GUILayout.Height(window.position.height - previewDraggableSeparator.value - 52));
			switch (tab)
			{
				case 0:
					DrawObjectControls();
					break;
				case 1:
					DrawCameraControls();
					break;
				case 2:
					DrawLightingControls();
					break;
				case 3:
					DrawPostProcessingControls();
					break;
				case 4:
					DrawExportControls();
					break;
			}

			if (tab < 4)
			{
				if (GUILayout.Button("Apply to All Selected Icons"))
					ApplyToAllSelectedIcons(tab);
			}
			GUILayout.EndScrollView();

		}

		void ApplyToAllSelectedIcons(int tab)
		{
			int result = 1;
			result = EditorUtility.DisplayDialogComplex("Apply to All Selected Icons", "Would you like to apply only " + tabNames[tab] + " settings, or all settings?", tabNames[tab] + " Settings Only", "Cancel", "All Settings");

			if (result == 1)
				return;
			else
			{
				int index = 1;

				Undo.RegisterCompleteObjectUndo(window, "Apply to all icons");

				foreach(Icon icon in assetGrid.selectedIcons)
				{
					if (icon != currentIcon)
					{
						EditorUtility.DisplayProgressBar("Updating Icons (" + index + "/" + (assetGrid.selectedIcons.Count - 1) + ")", icon.assetPath, ((float)index++ / (assetGrid.selectedIcons.Count - 1)));
						CopyIconSettings(currentIcon, icon, result == 2 ? -1 : tab);
						icon.SaveMatInfo();
						icon.saveData = true;
						UpdateIcon(icon);
					}
				}

				if (tab == 3 || tab == -1)
				{
					Editor.DestroyImmediate(materialEditor);
					materialEditor = (MaterialEditor)Editor.CreateEditor((UnityEngine.Object)reorderableList.list[reorderableList.index]);
				}

				EditorUtility.ClearProgressBar();
			}
		}

		void CopyIconSettings(Icon from, Icon to, int tab)
		{
			if (tab == 0 || tab == -1)
			{
				to.objectPosition = from.objectPosition;
				to.cameraRotation = from.cameraRotation;
				to.objectScale = from.objectScale;
			}

			if (tab == 1 || tab == -1)
			{
				to.cameraPosition = from.cameraPosition;
				to.cameraRotation = from.cameraRotation;
				to.cameraOrtho = from.cameraOrtho;
				to.cameraFov = from.cameraFov;
				to.cameraSize = from.cameraSize;
			}

			if (tab == 2 || tab == -1)
			{
				to.ambientLightColour = from.ambientLightColour;
				to.lightColour = from.lightColour;
				to.lightDir = from.lightDir;
				to.lightIntensity = from.lightIntensity;
			}
			
			if (tab == 3 || tab == -1)
			{
				foreach (Material mat in to.postProcessingMaterials)
					Editor.DestroyImmediate(mat);

				to.postProcessingMaterials.Clear();

				foreach (Material mat in from.postProcessingMaterials)
				{
					Material newMat = new Material(mat);
					to.postProcessingMaterials.Add(newMat);
					to.materialDisplayNames.Add(newMat, from.materialDisplayNames[mat]);
					to.materialToggles.Add(newMat, from.materialToggles[mat]);
				}
			}

			if (tab == 4 || tab == -1)
			{
				to.exportResolution = from.exportResolution;
				to.exportFolderPath = from.exportFolderPath;
			}

			to.saveData = true;
		}

		void DrawImageControls()
		{
			EditorGUI.BeginChangeCheck();

			//Texture2D tmpBgImage = (Texture2D)EditorGUILayout.ObjectField("Background Image", currentIcon.bgImage, typeof(Texture2D), false, GUILayout.Width(200));
			//Texture2D tmpFgImage= (Texture2D)EditorGUILayout.ObjectField("Foreground Image", currentIcon.fgImage, typeof(Texture2D), false, GUILayout.Width(200));
			//Texture2D tmpMask = (Texture2D)EditorGUILayout.ObjectField("Mask Image", currentIcon.mask, typeof(Texture2D), false, GUILayout.Width(200)); 

			if(EditorGUI.EndChangeCheck())
			{
				Undo.RecordObject(window, "Changed Icon Images");
				//currentIcon.bgImage = tmpBgImage;
				//currentIcon.fgImage = tmpFgImage;
				//currentIcon.mask = tmpMask;

				currentIcon.saveData = true;
				updateFlag = true;
			}
		}

		void DrawObjectControls()
		{
			EditorGUI.BeginChangeCheck();
			Vector3 tmpObjPos = EditorGUILayout.Vector3Field("Position", currentIcon.objectPosition);
			Vector3 tmpObjRot = EditorGUILayout.Vector3Field("Rotation", currentIcon.objectRotation);
			Vector3 tmpObjScale = EditorGUILayout.Vector3Field("Scale", currentIcon.objectScale);

			Rect r = GUILayoutUtility.GetLastRect();
			r.position += new Vector2(40, 0);
			if(GUI.Button(r, linkScale ? scaleLinkOnImage : scaleLinkOffImage, GUIStyle.none))
			{
				linkScale = !linkScale;
			}

			if (EditorGUI.EndChangeCheck())
			{
				Undo.RecordObject(window, "Edit Icon Object");
				currentIcon.objectPosition = tmpObjPos;
				currentIcon.objectRotation = tmpObjRot;

				if (!linkScale)
				{
					currentIcon.objectScale = tmpObjScale;
				}
				else
				{
					if(tmpObjScale.x != currentIcon.objectScale.x)
					{
						currentIcon.objectScale = tmpObjScale.x * Vector3.one;
					}
					else if (tmpObjScale.y != currentIcon.objectScale.y)
					{
						currentIcon.objectScale = tmpObjScale.y * Vector3.one;
					}
					else if (tmpObjScale.z != currentIcon.objectScale.z)
					{
						currentIcon.objectScale = tmpObjScale.z * Vector3.one;
					}
				}

				currentIcon.saveData = true;
				updateFlag = true;
			}
		}

		void DrawCameraControls()
		{
			EditorGUI.BeginChangeCheck();
			Vector3 tmpCamPos = EditorGUILayout.Vector3Field("Position", currentIcon.cameraPosition);
			Vector3 tmpCamRot = EditorGUILayout.Vector3Field("Rotation", currentIcon.cameraRotation);

			GUILayout.Space(5);
			string[] listOptions = { "Perspective", "Orthographic" };
			float tmpWdith = EditorGUIUtility.labelWidth;
			EditorGUIUtility.labelWidth = 80;
			int tmpOrtho = EditorGUILayout.Popup("Projection", currentIcon.cameraOrtho ? 1 : 0, listOptions);

			float tmpSizeFov;
			if (tmpOrtho == 1)
				tmpSizeFov = EditorGUILayout.FloatField("Size", currentIcon.cameraSize);
			else
				tmpSizeFov = EditorGUILayout.FloatField("Field of View", currentIcon.cameraFov);

			EditorGUIUtility.labelWidth = tmpWdith;

			if (EditorGUI.EndChangeCheck())
			{
				Undo.RecordObject(window, "Edit Icon Camera");
				currentIcon.cameraPosition = tmpCamPos;
				currentIcon.cameraRotation = tmpCamRot;
				currentIcon.cameraOrtho = tmpOrtho == 1 ? true : false;

				if (currentIcon.cameraOrtho)
					currentIcon.cameraSize = tmpSizeFov;
				else
					currentIcon.cameraFov = tmpSizeFov;

				currentIcon.saveData = true;
				updateFlag = true;
			}
		}

		void DrawLightingControls()
		{
			EditorGUI.BeginChangeCheck();
			Color tmpAmbLight = EditorGUILayout.ColorField("Ambient Light Colour", currentIcon.ambientLightColour);

			EditorGUILayout.Space(4);
			EditorGUILayout.LabelField("Directional Light");

			Color tmpLightColour = EditorGUILayout.ColorField("Colour", currentIcon.lightColour);
			Vector3 tmpLightDir = EditorGUILayout.Vector3Field("Rotation", currentIcon.lightDir);
			float tmpLightIntensity = EditorGUILayout.FloatField("Intensity", currentIcon.lightIntensity);

			if (EditorGUI.EndChangeCheck())
			{
				Undo.RecordObject(window, "Edit Icon Lighting");

				currentIcon.ambientLightColour = tmpAmbLight;

				currentIcon.lightColour = tmpLightColour;
				currentIcon.lightDir = tmpLightDir;
				currentIcon.lightIntensity = tmpLightIntensity;

				currentIcon.saveData = true;
				updateFlag = true;
			}
		}

		void DrawPostProcessingControls()
		{
			reorderableList.list = currentIcon.postProcessingMaterials;
			reorderableList.index = (int)Mathf.Clamp(reorderableList.index, 0, reorderableList.list.Count - 1);

			GUILayout.Space(2);

			reorderableList.DoLayoutList();

			EditorGUI.BeginChangeCheck();
			if (reorderableList.list.Count > 0)
			{
				string shaderName = currentIcon.postProcessingMaterials[reorderableList.index].shader.name;

				if (shaderName != "RapidIcon/ObjectRender")
				{
					GUILayout.Label("Shader Settings (" + shaderName + ")");

					UnityEngine.Object[] obj = new UnityEngine.Object[1];
					obj[0] = (UnityEngine.Object)reorderableList.list[reorderableList.index];
					MaterialProperty[] props = MaterialEditor.GetMaterialProperties(obj);

					GUILayout.BeginVertical(GUI.skin.box);
					if (materialEditor.customShaderGUI == null)
					{
						foreach (MaterialProperty prop in props)
						{
							if (prop.name != "_MainTex" && prop.flags != MaterialProperty.PropFlags.HideInInspector)
							{
								materialEditor.ShaderProperty(prop, prop.displayName);
							}
						}
					}
					else
					{
						List<MaterialProperty> list = new List<MaterialProperty>(props);
						foreach (MaterialProperty prop in list)
						{
							if (prop.name == "_MainTex")
							{
								list.Remove(prop);
								break;
							}
						}
						props = list.ToArray();

						materialEditor.customShaderGUI.OnGUI(materialEditor, props);
					}
					GUILayout.EndVertical();
				}
			}

			if (EditorGUI.EndChangeCheck())
			{
				currentIcon.SaveMatInfo();
				updateFlag = true;
			}
		}

		void DrawHeader(Rect rect)
		{
			EditorGUI.LabelField(rect, "Shaders");

			rect.width = 100;
			rect.x = sepWidth - 154;
			if(GUI.Button(rect, "Save Preset"))
			{
				string savePath = EditorUtility.SaveFilePanel("Save Preset", lastPresetPath == "" ? Application.dataPath : lastPresetPath, "PostProcessingPreset", "rippp");
				if (savePath != "")
				{
					currentIcon.SaveMatInfo();
					string data = JsonUtility.ToJson(currentIcon);
					int pos = data.IndexOf("\"matInfo\":");
					data = "{" + data.Substring(pos);

					File.WriteAllBytes(savePath, System.Text.Encoding.ASCII.GetBytes(data));
					lastPresetPath = savePath;
				}
			}

			rect.x += 102;
			if(GUI.Button(rect, "Load Preset"))
			{
				string openPath = EditorUtility.OpenFilePanel("Open Preset", lastPresetPath == "" ? Application.dataPath: lastPresetPath, "rippp");
				if (openPath != "")
				{
					Byte[] bytes = File.ReadAllBytes(openPath);
					lastPresetPath = openPath;
					string data = System.Text.Encoding.ASCII.GetString(bytes);

					Icon tmp = JsonUtility.FromJson<Icon>(data);

					currentIcon.saveData = true;
					currentIcon.matInfo = new List<Icon.MaterialInfo>(tmp.matInfo);
					currentIcon.LoadMatInfo();
					UpdateIcon(currentIcon);
					reorderableList.list = currentIcon.postProcessingMaterials;
					reorderableList.index = 0;
					Editor.DestroyImmediate(materialEditor);
					materialEditor = (MaterialEditor)Editor.CreateEditor((UnityEngine.Object)reorderableList.list[reorderableList.index]);
				}
			}
		}

		void DrawListItems(Rect rect, int index, bool isActive, bool isFocused)
		{
			if (index >= 0 && index < reorderableList.list.Count)
			{
				float[] widths = new float[] { 16, (sepWidth - 150) / 2, (sepWidth + 100) / 2, 80 };

				if (currentIcon.materialToggles == null)
				{
					window.Close();
					return;
				}

				GUI.enabled = currentIcon.materialToggles[currentIcon.postProcessingMaterials[index]];
				currentIcon.materialDisplayNames[currentIcon.postProcessingMaterials[index]] = EditorGUI.TextField(new Rect(rect.x+widths[0]+4, rect.y + 3, widths[1], EditorGUIUtility.singleLineHeight), currentIcon.materialDisplayNames[currentIcon.postProcessingMaterials[index]]);

				EditorGUI.BeginChangeCheck();
				GUI.enabled = true;
				currentIcon.materialToggles[currentIcon.postProcessingMaterials[index]] = EditorGUI.Toggle(new Rect(rect.x, rect.y + 3, widths[0], EditorGUIUtility.singleLineHeight), currentIcon.materialToggles[currentIcon.postProcessingMaterials[index]]);

				GUI.enabled = currentIcon.materialToggles[currentIcon.postProcessingMaterials[index]];
				currentIcon.postProcessingMaterials[index].shader = (Shader)EditorGUI.ObjectField(new Rect(rect.x + widths[0] + widths[1] + 8, rect.y + 3, widths[2], EditorGUIUtility.singleLineHeight), currentIcon.postProcessingMaterials[index].shader, typeof(Shader), true);
				GUI.enabled = true;

				if (EditorGUI.EndChangeCheck())
				{
					updateFlag = true;
					Editor.DestroyImmediate(materialEditor);
					materialEditor = (MaterialEditor)Editor.CreateEditor((UnityEngine.Object)reorderableList.list[reorderableList.index]);
				}
			}
		}

		void SelectShader(ReorderableList l)
		{
			Editor.DestroyImmediate(materialEditor);
			materialEditor = (MaterialEditor)Editor.CreateEditor((UnityEngine.Object)reorderableList.list[reorderableList.index]);
		}

		void AddShader(ReorderableList l)
		{
			Undo.RecordObject(window, "Add New Shader");

			Material m = new Material(Shader.Find("RapidIcon/ObjectRender"));
			
			l.list.Add(m);
			l.index = l.list.Count - 1;

			currentIcon.materialDisplayNames.Add(m, "Shader " + l.list.Count);
			currentIcon.materialToggles.Add(m, true);

			Editor.DestroyImmediate(materialEditor);
			materialEditor = (MaterialEditor)Editor.CreateEditor((UnityEngine.Object)reorderableList.list[reorderableList.index]);

			currentIcon.saveData = true;
			updateFlag = true;
		}

		void RemoveShader(ReorderableList l)
		{
			Undo.RecordObject(window, "Remove Shader");
			l.list.Remove(l.list[l.index]);
			l.index = (int)Mathf.Clamp(l.index, 0, l.list.Count - 1);

			Editor.DestroyImmediate(materialEditor);
			if(l.list.Count > 0)
				materialEditor = (MaterialEditor)Editor.CreateEditor((UnityEngine.Object)reorderableList.list[reorderableList.index]);

			currentIcon.saveData = true;
			updateFlag = true;
		}

		void ShadersReorded(ReorderableList l)
		{
			currentIcon.saveData = true;
			updateFlag = true;
		}

		void DrawExportControls()
		{
			EditorGUI.BeginChangeCheck();

			Vector2Int tmpExportRes = EditorGUILayout.Vector2IntField("Export Resolution", currentIcon.exportResolution);
			tmpExportRes.x = (int)Mathf.Clamp(tmpExportRes.x, 8, 2048);
			tmpExportRes.y = (int)Mathf.Clamp(tmpExportRes.y, 8, 2048);

			GUILayout.Space(2);

			GUILayout.BeginHorizontal();
			if (currentIcon.exportFolderPath[currentIcon.exportFolderPath.Length - 1] != '/')
				currentIcon.exportFolderPath += "/";

			float tmpWdith = EditorGUIUtility.labelWidth;
			EditorGUIUtility.labelWidth = 80;
			currentIcon.exportFolderPath = EditorGUILayout.TextField("Export Folder", currentIcon.exportFolderPath);
			EditorGUIUtility.labelWidth = tmpWdith;
			if (GUILayout.Button("Browse", GUILayout.Width(100)))
			{
				string folder = EditorUtility.OpenFolderPanel("Export Folder", currentIcon.exportFolderPath, "");
				if (folder != "")
				{
					string dataPath = Application.dataPath;
					dataPath = dataPath.Substring(0, dataPath.LastIndexOf('/') + 1);
					folder = folder.Replace(dataPath, "");
					currentIcon.exportFolderPath = folder;
				}
			}
			if (EditorGUI.EndChangeCheck())
			{
				Undo.RecordObject(window, "Edit Icon Export Resolution");
				currentIcon.exportResolution = tmpExportRes;

				if (currentIcon.exportResolution.x > 0 && currentIcon.exportResolution.y > 0)
				{
					currentIcon.saveData = true;
					updateFlag = true;
				}
			}
					   
			GUILayout.EndHorizontal();

			if (GUILayout.Button("Apply to All Selected Icons"))
				ApplyToAllSelectedIcons(4);

			GUILayout.Space(12);

			GUILayout.BeginHorizontal();
			GUILayout.FlexibleSpace();
			Rect r = GUILayoutUtility.GetRect(sepWidth, 1);
			GUI.DrawTexture(r, separatorTex);
			GUILayout.FlexibleSpace();
			GUILayout.EndHorizontal();

			GUILayout.Space(12);

			GUILayout.BeginHorizontal();
			GUILayout.FlexibleSpace();
			if (GUILayout.Button("Export Icon", GUILayout.Width(160)))
			{
				ExportIcon(currentIcon, false);
				FinishExportIcon(currentIcon);
				replaceAll = false;
			}
			else if (GUILayout.Button("Export Selected Icons", GUILayout.Width(160)))
			{
				AssetDatabase.StartAssetEditing();
				int index = 1;
				List<string> exportPaths = new List<string>();
				foreach (Icon icon in assetGrid.selectedIcons)
				{
					EditorUtility.DisplayProgressBar("Exporting Icons (" + index + "/" + assetGrid.selectedIcons.Count + ")", icon.assetPath, ((float)index++ / assetGrid.selectedIcons.Count));
					ExportIcon(icon, assetGrid.selectedIcons.Count > 1 ? true : false);
				}
				EditorUtility.ClearProgressBar();

				AssetDatabase.StopAssetEditing();
				FinishExportIcon(assetGrid.selectedIcons);

				replaceAll = false;
			}
			GUILayout.EndHorizontal();

		}

	}
}