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

public static class ToolsHelper
{
    static FieldInfo s_Hidden;
    static ToolsHelper()
    {
        Type type = typeof(Tools);
        s_Hidden = type.GetField("s_Hidden", BindingFlags.NonPublic | BindingFlags.Static);
    }

    // hide default handles
    public static bool Hidden
    {
        get
        {
            return ((bool)s_Hidden.GetValue(null));
        }
        set
        {
            s_Hidden.SetValue(null, value);
        }
    }
}

public static class EditorGUIHelper
{
    #region methods
    delegate void DrawPropertiesExcludingDelegate(SerializedObject obj, params string[] propertyToExclude);
    static DrawPropertiesExcludingDelegate DrawPropertiesExcluding;
    #endregion

    #region Styles 
    static GUIStyle s_EditToolButtonStyle;
    #endregion

    static EditorGUIHelper()
    {
        SetupMethods();
        SetupGUIStyles();
    }

    static void SetupMethods()
    {
        DrawPropertiesExcluding = GetMethod<DrawPropertiesExcludingDelegate>(typeof(Editor), "DrawPropertiesExcluding", BindingFlags.Static | BindingFlags.NonPublic);
    }

    static void SetupGUIStyles()
    {
        s_EditToolButtonStyle = new GUIStyle("Button");
        s_EditToolButtonStyle.padding = new RectOffset(0, 0, 0, 0);
        s_EditToolButtonStyle.margin = new RectOffset(0, 0, 0, 0);
    }

    private static T GetMethod<T>(Type type, string name) where T : Delegate
    {
        var method = type.GetMethod(name);
        T del = (T)Delegate.CreateDelegate(typeof(T), method);
        return del;
    }

    private static T GetMethod<T>(Type type, string name, BindingFlags flag) where T : Delegate
    {
        var method = type.GetMethod(name, flag);
        T del = (T)Delegate.CreateDelegate(typeof(T), method);
        return del;
    }

    // 绘制默认inspector但不显示script
    public static bool DrawDefaultInspectorWithoutScriptField(this Editor Inspector)
    {
        EditorGUI.BeginChangeCheck();
        Inspector.serializedObject.Update();
        SerializedProperty Iterator = Inspector.serializedObject.GetIterator();
        Iterator.NextVisible(true);
        while (Iterator.NextVisible(false))
        {
            EditorGUILayout.PropertyField(Iterator, true);
        }
        Inspector.serializedObject.ApplyModifiedProperties();
        return (EditorGUI.EndChangeCheck());
    }

    // 绘制默认inspector,但是不显示field
    public static void DrawDefaultInspectorWithoutField(SerializedObject obj, string field)
    {
        EditorGUI.BeginChangeCheck();
        DrawPropertiesExcluding(obj, field);
        if (EditorGUI.EndChangeCheck())
            obj.ApplyModifiedProperties();
    }

    // 控制tools开启的toggle
    public static bool DrawToolsToggle(this Editor caller, string label, GUIContent icon, bool toggle)
    {
        Rect controlRect = EditorGUILayout.GetControlRect(true, 20f, new GUILayoutOption[0]);
        Rect position = new Rect(controlRect.xMin + EditorGUIUtility.labelWidth, controlRect.yMin, 33f, 20f);
        GUIContent content = new GUIContent(label);
        Vector2 vector = GUI.skin.label.CalcSize(content);
        Rect position2 = new Rect(controlRect.xMin, controlRect.yMin + (controlRect.height - vector.y) * 0.5f, vector.x, controlRect.height);
        int instanceID = caller.GetInstanceID();
        GUI.Label(position2, label);
        toggle = GUI.Toggle(position, toggle, icon, s_EditToolButtonStyle);
        return toggle;
    }

    // 控制tools开启的toggle
    public static bool DrawToolsToggle(this Editor caller, string label, bool toggle)
    {
        Rect controlRect = EditorGUILayout.GetControlRect(true, 20f, new GUILayoutOption[0]);
        Rect position = new Rect(controlRect.xMin + EditorGUIUtility.labelWidth, controlRect.yMin, 33f, 20f);
        GUIContent content = new GUIContent(label);
        Vector2 vector = GUI.skin.label.CalcSize(content);
        Rect position2 = new Rect(controlRect.xMin, controlRect.yMin + (controlRect.height - vector.y) * 0.5f, vector.x, controlRect.height);
        int instanceID = caller.GetInstanceID();
        GUI.Label(position2, label);
        toggle = GUI.Toggle(position, toggle, "");
        return toggle;
    }

    // label    content
    public static void LabelField (string label, string content)
    {
        Rect controlRect = EditorGUILayout.GetControlRect(true, 20f, new GUILayoutOption[0]);
        Vector2 vector = GUI.skin.label.CalcSize(new GUIContent(label));
        EditorGUI.LabelField(new Rect(controlRect.xMin, controlRect.yMin, vector.x, 20f), label);
        vector = GUI.skin.label.CalcSize(new GUIContent(content));
        EditorGUI.LabelField(new Rect(controlRect.xMin + EditorGUIUtility.labelWidth, controlRect.yMin, vector.x, 20f), content);
    }

    // 靠右的label
    public static void LabelFieldRight(string content)
    {
        Rect controlRect = EditorGUILayout.GetControlRect(true, 20f, new GUILayoutOption[0]);
        Vector2 vector = GUI.skin.label.CalcSize(new GUIContent(content));
        EditorGUI.LabelField(new Rect(controlRect.xMin + EditorGUIUtility.labelWidth, controlRect.yMin, vector.x, 20f), content);
    }

    public static bool Button(string label, string content, int width)
    {
        Rect controlRect = EditorGUILayout.GetControlRect(true, 20f, new GUILayoutOption[0]);
        Vector2 vector = GUI.skin.label.CalcSize(new GUIContent(label));
        EditorGUI.LabelField(new Rect(controlRect.xMin, controlRect.yMin, vector.x, 20f), label);
        return GUI.Button(new Rect(controlRect.xMin + EditorGUIUtility.labelWidth, controlRect.yMin, width, 20f), content);
    }
    
    // label    button  tip
    public static bool Button(string label, string content, int width, string tip)
    {
        Rect controlRect = EditorGUILayout.GetControlRect(true, 20f, new GUILayoutOption[0]);
        Vector2 vector = GUI.skin.label.CalcSize(new GUIContent(label));
        EditorGUI.LabelField(new Rect(controlRect.xMin, controlRect.yMin, vector.x, 20f), label);
        bool clicked = GUI.Button(new Rect(controlRect.xMin + EditorGUIUtility.labelWidth, controlRect.yMin, width, 20f), content);
        EditorGUI.LabelField(new Rect(controlRect.xMin + EditorGUIUtility.labelWidth + width + 5, controlRect.yMin, vector.x, 20f), tip);
        return clicked;
    }

    // 按钮是图形而不是对勾的toggle
    public static bool ToggleButton(string label, bool value, GUIContent button)
    {
        Rect controlRect = EditorGUILayout.GetControlRect(true, 20f, new GUILayoutOption[0]);
        Rect position = new Rect(controlRect.xMin + EditorGUIUtility.labelWidth, controlRect.yMin, 33f, 20f);
        GUIContent content = new GUIContent(label);
        Vector2 vector = GUI.skin.label.CalcSize(content);
        Rect position2 = new Rect(controlRect.xMin, controlRect.yMin + (controlRect.height - vector.y) * 0.5f, vector.x, controlRect.height);
        GUI.Label(position2, label);
        value = GUI.Toggle(position, value, button, s_EditToolButtonStyle);
        return value;
    }
}