using UnityEditor;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;

public class EditorUtils
{
	public static readonly int NUM_BUILD_IN_PROPERTIES = 8;
	
	public delegate void RefreshTargetDelegate();
	public delegate void CreateListItemGUIDelegate( int index );
	public delegate T CreateNewListItemDelegate<T>( T before, T after );
	
	public static void UpdateListInspector<T>( ref List<T> list, RefreshTargetDelegate refreshTargetDelegate, CreateListItemGUIDelegate createItemGUIDelegate, CreateNewListItemDelegate<T> createNewItemDelegate )  where T : new()
	{
		GUILayout.Space(5);		
		
		int addAt = -2;
		int removeAt = -1;
		int upAt = -1;
		int downAt = -1;
		
		int count = list.Count;
		for (int i = 0; i < count; ++i )
		{
			EditorGUILayout.BeginHorizontal();
			
				//EditorGUILayout.BeginVertical(GUILayout.MaxWidth(25));
				EditorGUILayout.LabelField( i.ToString()+"-",EditorStyles.boldLabel, GUILayout.MaxWidth(17) );
				
				//EditorGUILayout.EndVertical();
			
				createItemGUIDelegate( i );
			
			
				if ( GUILayout.Button( new GUIContent("\u25B2"), EditorStyles.miniButtonLeft, GUILayout.MaxWidth(20) ) )
				{
					upAt = i;
				}
				if ( GUILayout.Button( new GUIContent("\u25BC"), EditorStyles.miniButtonMid,GUILayout.MaxWidth(20) ) )
				{
					downAt = i;
				}
				if ( GUILayout.Button( new GUIContent("+"), EditorStyles.miniButtonMid,GUILayout.MaxWidth(20) ) )
				{
					addAt = i;
				}
				if ( GUILayout.Button( new GUIContent("X"),  EditorStyles.miniButtonRight, GUILayout.MaxWidth(20) ) )
				{
					removeAt = i;
				}
			
			EditorGUILayout.EndHorizontal();
			
				
				//EditorGUILayout.BeginVertical(GUILayout.MaxWidth(40));
				
				//EditorGUILayout.EndVertical();
			
		}
		if ( count == 0 )
		{
			if ( GUILayout.Button( new GUIContent("+"), EditorStyles.miniButtonMid,GUILayout.MaxWidth(20) ) )
			{
				addAt = -1;
			}
		}
		
		if ( addAt >= -1 )
		{
			T prev = default(T);			
			T next = default(T);
			if ( addAt == -1 )
			{				
				if ( count > 0 )
				{
					prev = list[count-1];
				}
			}
			else 
			{
				prev = list[addAt];
			}
			
			if ( addAt+1 >= count )
			{			
				if ( count > 0 )
				{
					next = list[0];
				}		
			}
			else
			{
				next = list[addAt+1];
			}
			
			if ( createNewItemDelegate != null )
				list.Insert(addAt+1, createNewItemDelegate( prev, next ) );			
			else
				list.Insert(addAt+1, new T() );			
			
			
			if ( refreshTargetDelegate != null )
				refreshTargetDelegate();
		}
		
		else if ( removeAt >= 0 )
		{
			list.RemoveAt(removeAt);
			
			if ( refreshTargetDelegate != null )
				refreshTargetDelegate();	
		}		
		
		else if ( upAt > 0 )
		{
			T temp = list[upAt-1];
			list[upAt-1] = list[upAt];
			list[upAt] = temp;
			
			if ( refreshTargetDelegate != null )
				refreshTargetDelegate();
		}
		else if ( downAt >= 0 && downAt < list.Count-1)
		{
			T temp = list[downAt];
			list[downAt] = list[downAt+1];
			list[downAt+1] = temp;
			
			if ( refreshTargetDelegate != null )
				refreshTargetDelegate();
		}
		
	}
	
}


[CustomPropertyDrawer (typeof (MinMaxRange))]
public class MinMaxRangeDrawer : PropertyDrawer
{
    public override void OnGUI (Rect pos, SerializedProperty prop, GUIContent label) 
	{
		//EditorGUIUtility.LookLikeControls ();
		
		EditorGUI.BeginProperty(pos, label, prop);
		
	    SerializedProperty min = prop.FindPropertyRelative ("m_min");
	    SerializedProperty max = prop.FindPropertyRelative ("m_max");
		SerializedProperty hasMax = prop.FindPropertyRelative("m_hasMax");
		SerializedProperty hasValue = prop.FindPropertyRelative("m_hasValue");
			
		float toWidth = 30;
		float buttonWidth = 20;
		
		float rectWidth = (pos.width-toWidth)*0.4f;		
        pos = EditorGUI.PrefixLabel (pos, GUIUtility.GetControlID (FocusType.Passive), label);
		//EditorGUI.LabelField( new Rect(posX, pos.y,rectWidth, pos.height), prop.name);
		//posX += rectWidth;
		float posX = pos.x;
		
		 // Don't make child fields be indented
        int indent = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 0;
				
		if ( min != null && max != null && hasMax != null )
		{
			bool hasMaxVal = hasMax.boolValue;
			
			if ( hasMaxVal == false )
			{
				rectWidth = pos.width-buttonWidth;
			}
			else
			{
				rectWidth = (pos.width-buttonWidth-toWidth)*0.5f;
			}
			
			// EditorGUI.IndentedRect(new Rect(posX, pos.y,rectWidth, pos.height));
			EditorGUI.BeginChangeCheck ();			
			float minVal = EditorGUI.FloatField( new Rect(posX, pos.y,rectWidth, pos.height), min.floatValue);			
			if ( EditorGUI.EndChangeCheck() )
			{
				min.floatValue = minVal;
				if ( max.floatValue < minVal )
				{
					max.floatValue = minVal;
				}	
				hasValue.boolValue = false;
			}
			
			if ( hasMaxVal )
			{
				
				posX += rectWidth;
				
				EditorGUI.LabelField( new Rect(posX, pos.y,toWidth, pos.height), "to");
				posX += toWidth;
				
				// EditorGUI.IndentedRect(new Rect(posX, pos.y,rectWidth, pos.height));
				EditorGUI.BeginChangeCheck ();			
				float maxVal = EditorGUI.FloatField( new Rect(posX, pos.y,rectWidth, pos.height), max.floatValue);
				if ( EditorGUI.EndChangeCheck() )
				{
					max.floatValue = maxVal;
					hasValue.boolValue = false;
				}
			}			
			posX += rectWidth;
			
			// button
			EditorGUI.BeginChangeCheck ();		
			hasMaxVal = EditorGUI.Toggle(new Rect(posX, pos.y, buttonWidth, pos.height),hasMaxVal);
			
			if ( EditorGUI.EndChangeCheck() )
			{
				hasMax.boolValue = hasMaxVal;
				hasValue.boolValue = false;
			}
		}
		else
		{
			Debug.LogWarning("Min or max properties null");
		}
		
        EditorGUI.indentLevel = indent;
		
		EditorGUI.EndProperty();
		
		//EditorGUILayout.LabelField("Yo dawg!");
	}
	
}

public static class EditorExtension
{
	public static int DrawBitMaskField (Rect aPosition, int aMask, System.Type aType, GUIContent aLabel)
	{
		var itemNames = System.Enum.GetNames(aType);
		var itemValues = System.Enum.GetValues(aType) as int[];
		
		int val = aMask;
		int maskVal = 0;
		for(int i = 0; i < itemValues.Length; i++)
		{
			if (itemValues[i] != 0)
			{
				if ((val & itemValues[i]) == itemValues[i])
					maskVal |= 1 << i;
			}
			else if (val == 0)
				maskVal |= 1 << i;
		}
		int newMaskVal = EditorGUI.MaskField(aPosition, aLabel, maskVal, itemNames);
		int changes = maskVal ^ newMaskVal;
		
		for(int i = 0; i < itemValues.Length; i++)
		{
			if ((changes & (1 << i)) != 0)            // has this list item changed?
			{
				if ((newMaskVal & (1 << i)) != 0)     // has it been set?
				{
					if (itemValues[i] == 0)           // special case: if "0" is set, just set the val to 0
					{
						val = 0;
						break;
					}
					else
						val |= itemValues[i];
				}
				else                                  // it has been reset
				{
					val &= ~itemValues[i];
				}
			}
		}
		return val;
	}
}

[CustomPropertyDrawer(typeof(BitMaskAttribute))]
public class EnumBitMaskPropertyDrawer : PropertyDrawer
{
	public override void OnGUI (Rect position, SerializedProperty prop, GUIContent label)
	{
		var typeAttr = attribute as BitMaskAttribute;
		// Add the actual int value behind the field name
		label.text = label.text + "("+prop.intValue+")";
		prop.intValue = EditorExtension.DrawBitMaskField(position, prop.intValue, typeAttr.propType, label);
	}
}

// Press Alt-Enter to add new line in text box in inspector
public class CreateNewLine : EditorWindow
{
	[MenuItem("Edit/Insert New Line &\r")]
	static void InsertNewLine()
	{
		EditorGUIUtility.systemCopyBuffer = System.Environment.NewLine;
		EditorWindow.focusedWindow.SendEvent(EditorGUIUtility.CommandEvent("Paste"));
	}
}
