﻿using UnityEngine;
using UnityEngine.Animations;
using UnityEditor;
using UnityEditor.Animations;
using VRC.SDK3.Avatars.Components;
using VRC.SDK3.Avatars.ScriptableObjects;
using System.IO;


namespace CRPen2
{
    public partial class CRPen2Editor : Editor
    {
        private void Inspector()
        {
            GUIStyle guiStyleTitle = new GUIStyle();
            guiStyleTitle.fontStyle = FontStyle.Bold;
            guiStyleTitle.normal.textColor = GUI.color;

            CRPen2Setting script = (CRPen2Setting)target;

            GuiLine();

            // Avatar.
            EditorGUI.BeginChangeCheck();
            EditorGUILayout.PropertyField(_avatar, new GUIContent("Avatar"));
            if (EditorGUI.EndChangeCheck())
            {
                serializedObject.ApplyModifiedProperties();
                if (script.avatar)
                {
                    // Auto Hand Setting.
                    Animator animator = script.avatar.gameObject.GetComponent<Animator>();
                    if (animator.isHuman)
                    {
                        script.inkPosition = animator.GetBoneTransform(HumanBodyBones.RightHand);
                        script.canvasPosition = animator.GetBoneTransform(HumanBodyBones.LeftHand);
                    }
                }                
            }

            GuiLine();
            GUILayout.Label("Hand Setting", guiStyleTitle);

            EditorGUILayout.PropertyField(_inkPosition, new GUIContent("Ink Hand"));
            EditorGUILayout.PropertyField(_canvasPosition, new GUIContent("Canvas Hand"));

            GuiLine();
            GUILayout.Label("Pen Setting", guiStyleTitle);

            EditorGUILayout.Slider(_lifetime, 0, 180, new GUIContent("Lifetime"));
            EditorGUILayout.PropertyField(_size, new GUIContent("Size"));
            EditorGUILayout.PropertyField(_drawGesture, new GUIContent("DrawGesture"));
            EditorGUILayout.PropertyField(_hand, new GUIContent("Use Hand"));
            EditorGUILayout.PropertyField(_handClip, new GUIContent("Hand Animation"));

            GuiLine();
            GUILayout.Label("Parameter Setting", guiStyleTitle);

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PropertyField(_useGrip, new GUIContent("Use Grip"));
            ParameterOptionText(script.useGrip, 1);
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PropertyField(_useColor, new GUIContent("Use Color"));
            ParameterOptionText(script.useColor, 8);
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PropertyField(_useSize, new GUIContent("Use Size"));
            ParameterOptionText(script.useSize, 8);
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PropertyField(_useEmission, new GUIContent("Use Emission"));
            ParameterOptionText(script.useEmission, 8);
            EditorGUILayout.EndHorizontal();

            GuiLine();
            GUILayout.Label("Apply Setting", guiStyleTitle);
            EditorGUILayout.PropertyField(_applyDirectly, new GUIContent("Apply Directly"));

            GuiLine();

            ParameterInfo(_requiredParameter, _requiredEmptyParameter);

            GuiLine();

            serializedObject.ApplyModifiedProperties();
        }

        private void InspectorColor()
        {
            CRPen2Setting script = (CRPen2Setting)target;

            // Color Count.
            EditorGUI.BeginChangeCheck();
            script.colorCount = EditorGUILayout.IntSlider("Color Count", script.colorCount, 1, 8);

            // Color List.
            for (int i = 0; i < script.colorCount; i++)
            {
                script.colorList[i] = EditorGUILayout.ColorField("Color " + i, script.colorList[i]);
            }
        }

        private bool Check()
        {
            bool result = false;
            CRPen2Setting script = (CRPen2Setting)target;

            if (!script.root || _rootDir == null)
            {
                EditorGUILayout.HelpBox("Root", MessageType.Error);
                result = true;
            }

            if (!script.penPrefab)
            {
                EditorGUILayout.HelpBox("penPrefab", MessageType.Error);
                result = true;
            }

            if (!_inkTarget)
            {
                EditorGUILayout.HelpBox("Not Found InkPosition", MessageType.Error);
                result = true;
            }

            if (!script.avatar)
            {
                EditorGUILayout.HelpBox("Avatar is not specified.", MessageType.Error);
                result = true;
            }

            if (!script.inkPosition)
            {
                EditorGUILayout.HelpBox("InkHand is not specified.", MessageType.Error);
                result = true;
            }

            if (!script.canvasPosition)
            {
                EditorGUILayout.HelpBox("CanvasHand is not specified.", MessageType.Error);
                result = true;
            }

            if (script.size <= 0)
            {
                EditorGUILayout.HelpBox("Size must be greater than 0.", MessageType.Error);
                result = true;
            }

            if (script.avatar && script.avatar.expressionParameters)
            {
                int requireParam = script.avatar.expressionParameters.CalcTotalCost() + _requiredEmptyParameter;

                if (requireParam > 128)
                {
                    EditorGUILayout.HelpBox(_requiredEmptyParameter + " parameters are required", MessageType.Error);
                    result = true;
                }
            }

            return result;
        }

        private int CountRequiredParameter()
        {
            CRPen2Setting script = (CRPen2Setting)target;

            if (!script.avatar || !script.avatar.expressionParameters)
                return 0;

            int requiredParameter = 2;
            if (script.useGrip == true) requiredParameter += 1;
            if (script.useColor == true) requiredParameter += 8;
            if (script.useSize == true) requiredParameter += 8;
            if (script.useEmission == true) requiredParameter += 8;

            return requiredParameter;
        }

        private int CountEmptyRequiredParameter()
        {
            CRPen2Setting script = (CRPen2Setting)target;

            if (!script.avatar || !script.avatar.expressionParameters)
                return 0;

            int requiredEmptyParameter = 0;
            VRCExpressionParameters param = script.avatar.expressionParameters;

            if (param.FindParameter("PenUse") == null) requiredEmptyParameter += 1;
            if (param.FindParameter("PenErase") == null) requiredEmptyParameter += 1;
            if (script.useColor == true && param.FindParameter("PenColor") == null) requiredEmptyParameter += 8;
            if (script.useGrip == true && param.FindParameter("PenGrip") == null) requiredEmptyParameter += 1;
            if (script.useSize == true && param.FindParameter("PenSize") == null) requiredEmptyParameter += 8;
            if (script.useEmission == true && param.FindParameter("PenEmission") == null) requiredEmptyParameter += 8;

            return requiredEmptyParameter;
        }

        // Parameter Info.
        private void ParameterInfo(int requiredParameter, int requiredEmptyParameter)
        {
            CRPen2Setting script = (CRPen2Setting)target;

            GUIStyle style = new GUIStyle();
            style.normal.textColor = GUI.color;

            // Main Text.            
            if (script.avatar && script.avatar.expressionParameters)
            {
                int remainingParameters = 128 - script.avatar.expressionParameters.CalcTotalCost();

                GUILayout.Label("Tatal Parameters : " + requiredParameter, style);

                string duplicatedText = "";

                if (requiredParameter - requiredEmptyParameter != 0)
                    duplicatedText = " (" + (requiredParameter - requiredEmptyParameter) + " duplicated)";

                GUILayout.Label("Required Parameters : " + requiredEmptyParameter + duplicatedText, style);

                if (remainingParameters < requiredEmptyParameter)
                    style.normal.textColor = Color.red;

                GUILayout.Label("Activated Parameters : " + (128 - remainingParameters) + "/128 (" + remainingParameters + " remaining)", style);
            }
            else
            {
                GUILayout.Label("Tatal Parameters : ", style);
                GUILayout.Label("Required Parameters : ", style);
                GUILayout.Label("Activated Parameters : ", style);
            }
        }

        // Parameter Option Text.
        private void ParameterOptionText(bool print, int count)
        {
            if (print)
                GUILayout.Label("Parameter+" + count, GUILayout.Width(100));
            else
                GUILayout.Label(" ", GUILayout.Width(100));
        }

        //
        private void SetHand()
        {
            CRPen2Setting script = (CRPen2Setting)target;

            
        }
    }
}