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

[CustomEditor(typeof(T1AnimationAssistant))]
public class T1AnimationAssistantEditor : Editor
{
    private SerializedProperty animationsProp;

    void OnEnable()
    {
        animationsProp = serializedObject.FindProperty("animations");
    }

    public override void OnInspectorGUI()
    {
        serializedObject.Update();

        EditorGUILayout.PropertyField(animationsProp, new GUIContent("Animations"), true);

        serializedObject.ApplyModifiedProperties();
    }
}

[CustomPropertyDrawer(typeof(T1AnimEventMonoClip))]
public class T1AnimEventMonoClipDrawer : PropertyDrawer
{
    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        float height = EditorGUIUtility.singleLineHeight;
        if (property.isExpanded)
        {
            height = EditorGUIUtility.singleLineHeight * 4;
            SerializedProperty keyFramesProp = property.FindPropertyRelative("keyFrames");
            height += EditorGUI.GetPropertyHeight(keyFramesProp);
        }
        return height;
    }

    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        EditorGUI.BeginProperty(position, label, property);

        SerializedProperty animClipProp = property.FindPropertyRelative("animClip");
        SerializedProperty animIDProp = property.FindPropertyRelative("animID");
        SerializedProperty keyFramesProp = property.FindPropertyRelative("keyFrames");

        //Draw Foldout Description
        Rect propRect = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight);
        string desc = "No AnimationClip Set";
        if (animClipProp.objectReferenceValue != null)
        {
            desc = animClipProp.objectReferenceValue.name + " (ID: " + animIDProp.intValue + " Actions: " + keyFramesProp.arraySize + ")";
        }
        property.isExpanded = EditorGUI.Foldout(propRect, property.isExpanded, desc);
        if (property.isExpanded)
        {
            propRect.y += EditorGUIUtility.singleLineHeight;
            int indentLast = EditorGUI.indentLevel;
            EditorGUI.indentLevel++;

            EditorGUI.PropertyField(propRect, animClipProp, true);
            propRect.y += EditorGUIUtility.singleLineHeight;

            Rect animRect = propRect;
            animRect.width -= 30.0f;
            EditorGUI.PropertyField(animRect, animIDProp, true);
            animRect.x += animRect.width;
            animRect.width = 30.0f;
            if (GUI.Button(animRect, "..."))
            {
                T1DBEditorWindow.ShowWindow(animIDProp, T1DBEditorWindow.T1DBType.Animations);
            }

            propRect.y += EditorGUIUtility.singleLineHeight;

            SerializedProperty loopProp = property.FindPropertyRelative("loop");
            EditorGUI.PropertyField(propRect, loopProp, true);
            propRect.y += EditorGUIUtility.singleLineHeight;

            EditorGUI.PropertyField(propRect, keyFramesProp, new GUIContent("Key Frame Actions (" + keyFramesProp.arraySize + ")"), true);
            propRect.y += EditorGUIUtility.singleLineHeight;

            EditorGUI.indentLevel = indentLast;
        }

        EditorGUI.EndProperty();
    }
}

[CustomPropertyDrawer(typeof(T1AnimKeyFrameAction))]
public class T1AnimEventMonoActionDrawer : PropertyDrawer
{
    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        float height = EditorGUIUtility.singleLineHeight;
        if (property.isExpanded)
        {
            height = EditorGUIUtility.singleLineHeight * 7;
            if (property.FindPropertyRelative("animClip") != null)
                height += EditorGUIUtility.singleLineHeight;
            SerializedProperty eventTypeProp = property.FindPropertyRelative("eventType");
            string[] values;
            if (T1Utils.DBAnimActions.TryGetValue(eventTypeProp.intValue.ToString(), out values))
            {
                for (int i = 1; i < values.Length; i++)
                {
                    if (values[i] == "Sound ID" || values[i] == "Fx ID")
                    {
                        height += EditorGUIUtility.singleLineHeight;
                    }
                }
            }
        }
        return height;
    }

    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        EditorGUI.BeginProperty(position, label, property);

        SerializedProperty indexProp = property.FindPropertyRelative("index");
        SerializedProperty animClipProp = property.FindPropertyRelative("animClip");
        SerializedProperty frameProp = property.FindPropertyRelative("frame");
        SerializedProperty eventTypeProp = property.FindPropertyRelative("eventType");

        //Get Event Name and Arg Names from Event Type
        string[] animActionValues;
        T1Utils.DBAnimActions.TryGetValue(eventTypeProp.intValue.ToString(), out animActionValues);
        if (animActionValues == null)
            animActionValues = new string[0];

        //Get Description
        string desc = "";
        if (indexProp != null)
        {
            desc += indexProp.intValue + ": ";
        }
        if (animClipProp != null)
        {
            if (animClipProp.objectReferenceValue != null)
            {
                desc += animClipProp.objectReferenceValue.name + " - ";
                if (animActionValues.Length > 0)
                    desc += animActionValues[0];
                else
                    desc += "Custom";
                desc += " (Frame " + frameProp.intValue + ")";
            }
            else
            {
                desc += "No AnimationClip Set";
            }
        }
        else
        {
            if (animActionValues.Length > 0)
                desc += animActionValues[0];
            else
                desc += "Custom";
            desc += " (Frame " + frameProp.intValue + ")";
        }

        //Draw Foldout Description
        Rect propRect = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight);
        property.isExpanded = EditorGUI.Foldout(propRect, property.isExpanded, desc);
        if (property.isExpanded)
        {
            propRect.y += EditorGUIUtility.singleLineHeight;
            int indentLast = EditorGUI.indentLevel;
            EditorGUI.indentLevel++;

            //Draw AnimClip Field
            if (animClipProp != null)
            {
                EditorGUI.PropertyField(propRect, animClipProp, true);
                propRect.y += EditorGUIUtility.singleLineHeight;
            }

            //Draw Frame Field
            EditorGUI.PropertyField(propRect, frameProp, true);
            propRect.y += EditorGUIUtility.singleLineHeight;

            //Draw Event Field
            Rect eventRect = EditorGUI.PrefixLabel(propRect, new GUIContent("Event"));
            eventRect.x -= 30.0f;
            eventRect.width += 30.0f;
            eventRect.width -= 25.0f;
            EditorGUI.PropertyField(eventRect, eventTypeProp, GUIContent.none);
            eventRect.x += eventRect.width + 2.0f;
            eventRect.width = 25.0f - 2.0f;
            if (GUI.Button(eventRect, "..."))
            {
                T1DBEditorWindow.ShowWindow(eventTypeProp, T1DBEditorWindow.T1DBType.AnimActions);
            }
            propRect.y += EditorGUIUtility.singleLineHeight;

            //get Arg Names
            string[] argNames = new string[4];
            for (int i = 0; i < argNames.Length; i++)
            {
                int animActionIndex = i + 1;
                if (animActionIndex < animActionValues.Length)
                {
                    argNames[i] = animActionValues[animActionIndex];
                }
                else
                {
                    argNames[i] = "Arg " + i;
                }
            }

            //Draw Arg Fields
            for (int i = 0; i < argNames.Length; i++)
            {
                propRect = DrawArgField(propRect, property.FindPropertyRelative("arg" + i), argNames[i]);
                
            }

            EditorGUI.indentLevel = indentLast;
        }

        EditorGUI.EndProperty();
    }

    public bool IsArgDataBase(string argName)
    {
        return argName == "Sound ID" || argName == "Fx ID";
    }

    public bool IsArgNamedFloat(string argName)
    {
        return argName == "Unused" || argName == "X Offset" || argName == "Y Offset" || argName == "Z Offset";
    }

    public T1DBEditorWindow.T1DBType ArgNameToDBType(string argName)
    {
        if (argName == "Sound ID")
            return T1DBEditorWindow.T1DBType.Sounds;
        return T1DBEditorWindow.T1DBType.Fx;
    }

    public Rect DrawArgField(Rect propRect, SerializedProperty prop, string argName)
    {
        Rect argRect = propRect;
        argRect = EditorGUI.PrefixLabel(argRect, new GUIContent(argName));
        argRect.x -= 30.0f;
        argRect.width += 30.0f;
        if (IsArgDataBase(argName))
        {
            T1DBEditorWindow.T1DBType dbType = ArgNameToDBType(argName);
            string[] dbValues;
            if (dbType == T1DBEditorWindow.T1DBType.Sounds)
                T1Utils.DBSounds.TryGetValue(Mathf.FloorToInt(prop.floatValue).ToString(), out dbValues);
            else if (dbType == T1DBEditorWindow.T1DBType.AnimActions)
                T1Utils.DBAnimActions.TryGetValue(Mathf.FloorToInt(prop.floatValue).ToString(), out dbValues);
            else if (dbType == T1DBEditorWindow.T1DBType.Animations)
                T1Utils.DBAnimations.TryGetValue(Mathf.FloorToInt(prop.floatValue).ToString(), out dbValues);
            else
                T1Utils.DBFx.TryGetValue(Mathf.FloorToInt(prop.floatValue).ToString(), out dbValues);
            if (dbValues == null)
                dbValues = new string[0];
            if (dbValues.Length > 0)
            {
                if (dbValues.Length > 1 && (dbType == T1DBEditorWindow.T1DBType.Fx || dbType == T1DBEditorWindow.T1DBType.Sounds))
                    EditorGUI.LabelField(argRect, dbValues[1]);
                else
                    EditorGUI.LabelField(argRect, dbValues[0]);
            }
            else
            {
                EditorGUI.LabelField(argRect, "Custom");
            }
            argRect.y += EditorGUIUtility.singleLineHeight;
            argRect.width -= 25.0f;
            EditorGUI.PropertyField(argRect, prop, GUIContent.none);
            argRect.x += argRect.width + 2.0f;
            argRect.width = 25.0f - 2.0f;
            if (GUI.Button(argRect, "..."))
            {
                T1DBEditorWindow.ShowWindow(prop, dbType);
            }
            propRect.y += EditorGUIUtility.singleLineHeight;
        }
        else
        {
            if (IsArgNamedFloat(argName))
            {
                EditorGUI.PropertyField(argRect, prop, GUIContent.none);
            }
            else
            {
                argRect.width -= 25.0f;
                EditorGUI.PropertyField(argRect, prop, GUIContent.none);
                argRect.x += argRect.width + 2.0f;
                argRect.width = 25.0f - 2.0f;
                if (GUI.Button(argRect, "..."))
                {
                    GenericMenu menu = new GenericMenu();
                    menu.AddItem(new GUIContent("AnimActions"), false, OnDBAnimActionsSelected, prop);
                    menu.AddItem(new GUIContent("Animations"), false, OnDBAnimationsSelected, prop);
                    menu.AddItem(new GUIContent("Sounds"), false, OnDBSoundsSelected, prop);
                    menu.AddItem(new GUIContent("Fx"), false, OnDBFxSelected, prop);
                    menu.ShowAsContext();
                }
            }
        }
        propRect.y += EditorGUIUtility.singleLineHeight;
        return propRect;
    }

    void OnDBAnimActionsSelected(object objProp)
    {
        T1DBEditorWindow.ShowWindow((SerializedProperty)objProp, T1DBEditorWindow.T1DBType.AnimActions);
    }
    void OnDBAnimationsSelected(object objProp)
    {
        T1DBEditorWindow.ShowWindow((SerializedProperty)objProp, T1DBEditorWindow.T1DBType.Animations);
    }
    void OnDBSoundsSelected(object objProp)
    {
        T1DBEditorWindow.ShowWindow((SerializedProperty)objProp, T1DBEditorWindow.T1DBType.Sounds);
    }
    void OnDBFxSelected(object objProp)
    {
        T1DBEditorWindow.ShowWindow((SerializedProperty)objProp, T1DBEditorWindow.T1DBType.Fx);
    }
}
