using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using Fort23.Mono;
using Fort23.UTool;
using UnityEditor;
using UnityEngine;

using Object = UnityEngine.Object;

// namespace UnityEditor
// {
[CustomEditor(typeof(RectTransform))]
public class FortRectTransformInspector : UnityEditor.Editor
{
    private UnityEditor.Editor editor;

    private UnityEngine.Object openObject;
    private ReferenceCollector ReferenceCollector;
    private Dictionary<string, string> AllTypeDictionary = new Dictionary<string, string>();

    protected Canvas canvas;

    protected RectTransform rectTransform;

    void OnEnable()
    {
        try
        {
            canvas = null;
            Assembly assembly = Assembly.GetAssembly(typeof(UnityEditor.Editor));
            Type edi = assembly.GetType("UnityEditor.RectTransformEditor", false);
            editor = CreateEditor(target, edi);
            MethodInfo methodInfo = editor.GetType().GetMethod("OnEnable", BindingFlags.NonPublic | BindingFlags.Instance);
            methodInfo.Invoke(editor, null);

            rectTransform = serializedObject.targetObject as RectTransform;
            ReferenceCollector = rectTransform.gameObject.GetComponent<ReferenceCollector>();
            Type _type = null;
            openObject = OpenTargetUIScripts(rectTransform.gameObject.name, ref _type);
            if (_type != null)
            {
                object _typeObj = System.Activator.CreateInstance(_type);
                if (_typeObj is UIPanel)
                {
                    canvas = rectTransform.GetComponentInParent<Canvas>();
                }
            }
        }
        catch (Exception e)
        {
            LogTool.Error(e);
        }
    }

    public static UnityEngine.Object OpenTargetUIScripts(string prefabName, ref Type uiType)
    {
        string path = "Assets/Scripts/Mono/UI";
        string scriptPath = "";

        ArrayList alst = GetFile(path, ".cs");


        Type[] ALL = Assembly.Load(@"Fort23.Mono").GetTypes();
        for (int i = 0; i < ALL.Length; i++)
        {
            UIBindingAttribute uiBindingAttribute = ALL[i].GetCustomAttribute<UIBindingAttribute>();
            if (uiBindingAttribute != null)
            {
                if (uiBindingAttribute.prefab == prefabName)
                {
                    string n = ALL[i].Name;

                    for (var j = 0; j < alst.Count; j++)
                    {
                        string currPath = alst[j].ToString().ToLower().Replace("\\", "/");
                        string[] contentStrings = currPath.Split("/");
                        string end = contentStrings[contentStrings.Length - 1].Replace(".cs", "");

                        // if(end.Contains(n.ToLower()))
                        if (String.Equals(end, n.ToLower(), StringComparison.CurrentCultureIgnoreCase))
                        {
                            string s = alst[j].ToString();
                            s = s.Replace("\\", "/");
                            scriptPath = s.Replace(Application.dataPath, "Assets");
                            uiType = ALL[i];
                            break;
                        }
                    }

                    break;
                }
            }
        }

        UnityEngine.Object codeObject = AssetDatabase.LoadAssetAtPath(scriptPath, typeof(UnityEngine.Object));
        if (codeObject == null)
        {
            return null;
        }

        return codeObject;
    }

    public static ArrayList GetFile(string dir, string extension)
    {
        ArrayList alst = new ArrayList();
        string[] files = Directory.GetFiles(dir, ".", SearchOption.AllDirectories);
        foreach (string file in files)
        {
            string exname = file.Substring(file.LastIndexOf(".", StringComparison.Ordinal) + 1);
            if (extension.IndexOf(file.Substring(file.LastIndexOf(".", StringComparison.Ordinal) + 1), StringComparison.Ordinal) > -1)
            {
                FileInfo fi = new FileInfo(file);
                alst.Add(fi.FullName);
            }
        }

        return alst;
    }

    public string[] classType =
    {
        "Panel", "Component"
    };

    string selectedComponentName;
    [SerializeField] public string ClassName = "";


    public override void OnInspectorGUI()
    {
        if (editor == null)
        {
            return;
        }

        editor.OnInspectorGUI();
        if (canvas != null)
        {
            rectTransform.sizeDelta = canvas.GetComponent<RectTransform>().sizeDelta;
        }

        if (openObject != null)
        {
            GUILayout.BeginHorizontal();
            if (GUILayout.Button("打开脚本"))
            {
                AssetDatabase.OpenAsset(openObject, 1);
            }

            if (ReferenceCollector != null)
            {
                if (GUILayout.Button("生成TD脚本"))
                {
                    ShengChengDaiMa();
                }
            }

            GUILayout.EndHorizontal();
        }
        else
        {
            ClassName = EditorGUILayout.TextField("ClassName:", ClassName);
            GUILayout.BeginHorizontal(GUI.skin.box);
            foreach (var s in classType)
            {
                if (GUILayout.Toggle(selectedComponentName == s, s))
                {
                    selectedComponentName = s;
                }
            }

            EditorGUILayout.EndHorizontal();


            if (GUILayout.Button("生成UI脚本"))
            {
                string path = UnityEditor.EditorUtility.OpenFolderPanel("选择一个生成的路径", Application.dataPath + "/Scripts/Mono/UI", "");
                RectTransform rectTransform = serializedObject.targetObject as RectTransform;

                GenerateUIPanelCode(ClassName, rectTransform.name, path);
            }
        }
    }

    public string GetExtenstionClassName()
    {
        string name = String.Empty;

        if (selectedComponentName.Contains("Panel"))
        {
            name = "UIPanel";
        }

        if (selectedComponentName.Contains("Component"))
        {
            name = "UIComponent";
        }

        return name;
    }

    public void GenerateUIPanelCode(string callName, string prefabName, string path)
    {
        if (callName == String.Empty)
        {
            callName = prefabName;
        }

        string className = callName;
        string extenstionClass = GetExtenstionClassName();
        path += "/" + className + ".cs";
        StringBuilder code = new StringBuilder();

        if (File.Exists(path))
        {
            Debug.LogError("已经存在脚本");
            return;
        }


        code.Append("namespace Fort23.Mono\n{");
        code.Append("\n");
        code.Append($"[UIBinding(prefab = \"" + prefabName + "\"  )]");
        code.Append("\n");
        code.Append($"\tpublic partial class {className} : {extenstionClass}\n");
        code.Append("\t{\n");

        code.Append("\tprivate void Init()\n");
        code.Append("\t{\n");

        code.Append("\t}\n");


        if (!extenstionClass.Contains("UIComponent"))
        {
            code.Append("\tprotected override void AddEvent()\n");
            code.Append("\t{\n");
            code.Append("\t}\n");

            code.Append("\tprotected override void DelEvent()\n");
            code.Append("\t{\n");
            code.Append("\t}\n");
        }
        else
        {
            code.Append("\tpublic override void AddEvent()\n");
            code.Append("\t{\n");
            code.Append("\t}\n");

            code.Append("\tpublic override void DelEvent()\n");
            code.Append("\t{\n");
            code.Append("\t}\n");
        }


        code.Append("\tpublic override void AddButtonEvent()\n");
        code.Append("\t{\n");
        code.Append("\t}\n");


        code.Append("\n");

        code.Append("\t}\n");
        code.Append("}\n");

        File.WriteAllText(path, code.ToString());

        Debug.Log("代码自动生成成功");
        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
    }


    private void ShengChengDaiMa()
    {
        AllTypeDictionary.Clear();
        //更新

        if (ReferenceCollector != null)
        {
            foreach (var keyValuePair in ReferenceCollector.GetData())
            {
                try
                {
                    if (!keyValuePair.isList)
                    {
                        Object o = keyValuePair.gameObject;

                        AllTypeDictionary.Add(keyValuePair.key, o.GetType().Name);
                    }
                    else
                    {
                        AllTypeDictionary.Add(keyValuePair.key, "List<object>");
                    }
                }
                catch (Exception e)
                {
                    Debug.LogError(keyValuePair.key);
                    Debug.LogError(e);
                }
            }

            GenerateCode();
        }
    }

    public void GenerateCode()
    {
        string path = AssetDatabase.GetAssetPath(openObject);
        string className = openObject.name;
        className = className.Replace(".cs", "");
        StringBuilder code = new StringBuilder();

        string filePath = Application.dataPath.Replace("Assets", path);
        filePath = filePath.Replace("\\", "/");
        int index = filePath.LastIndexOf('/');
        filePath = filePath.Substring(0, index);

        GenerateDataCode(className, filePath);
    }

    /// <summary>
    /// 生成数据类
    /// </summary>
    /// <param name="isReGet"></param>
    public void GenerateDataCode(string calssName, string path)
    {
        string calssePath = path + "/" + calssName + "Data.cs";
        string className = calssName;

        StringBuilder code = new StringBuilder();


        code.Append("using Fort23.Core;\n");
        code.Append("using Fort23.UTool;\n");
        code.Append("using UnityEngine.UI;\n");
        code.Append("using UnityEngine;\n");
        code.Append("using System.Collections.Generic;\n");
        // code.Append("using Fort23.Mono.UI.Utility;\n");
        // code.Append("using UnityEngine.UI.Extensions;\n");
        // code.Append("using Mono.UI.AllComs;\n");
        // code.Append("using Mono.Utility;\n");
        code.Append("namespace Fort23.Mono\n{");
        code.Append("\n");
        code.Append($"\tpublic partial class {className} \n");
        code.Append("\t{\n");

        code.Append("\t  #region 自定义数据 \n");
        foreach (var keyValuePair in AllTypeDictionary)
        {
            code.Append($"\t  private {keyValuePair.Value} _{keyValuePair.Key};\n");
            code.Append($"\t  public {keyValuePair.Value} {keyValuePair.Key}\n");
            code.Append("\t   {\n");
            code.Append("\t   get{\n");
            code.Append($"\t      if (_{keyValuePair.Key} == null)\n");
            code.Append("\t       {\n");
            code.Append($"\t         _{keyValuePair.Key}  = GetUIUnit<{keyValuePair.Value}>(\"" + keyValuePair.Key + "\"); \n");
            code.Append("\t       }\n");
            code.Append($"\t      return _{keyValuePair.Key};\n");
            code.Append("\t     }\n");
            code.Append("\t   }\n");
        }


        code.Append("\t  #endregion 自定义数据结束 \n");

        code.Append("\t public override async CTask SetUIGameObject(GameObject gObjectPoolInterface)\n");
        code.Append("\t{\n");

        code.Append("\t await base.SetUIGameObject(gObjectPoolInterface);\n");
        // foreach (var keyValuePair in AllTypeDictionary)
        // {
        //     code.Append($"\t {keyValuePair.Key} = GetUIUnit<{keyValuePair.Value}>(\"" + keyValuePair.Key + "\"); \n");
        // }

        code.Append("\t Init();\n");

        code.Append("\t}\n");


        code.Append("\t}\n");
        code.Append("}\n");

        // if (isReGet)  这个脚本里面不在做其它事情，就是自动生成的代码，不用考虑自定义
        // {
        //     StringBuilder ss = new StringBuilder();
        //
        //     using (FileStream stream = File.OpenRead(calssePath))
        //     {
        //         using (StreamReader reader = new StreamReader(stream))
        //         {
        //             bool isIgnor = false;
        //             bool isAdd = false;
        //
        //             while (!reader.EndOfStream)
        //             {
        //                 string s = reader.ReadLine() + "\n";
        //
        //
        //                 if (isIgnor)
        //                 {
        //                     if (s.Contains("结束"))
        //                     {
        //                         break;
        //                     }
        //
        //                     ss.Append(s);
        //                 }
        //
        //                 if (s.Contains("自定义数据"))
        //                 {
        //                     isIgnor = true;
        //                 }
        //
        //
        //                 if (s.Contains("结束"))
        //                 {
        //                     isIgnor = false;
        //                 }
        //             }
        //         }
        //     }
        //
        //
        //     string text = ss.SplitToString() + "\t  ";
        //     string text2 = code.SplitToString();
        //
        //     int index = text2.IndexOf("#endregion 自定义数据结束 ", StringComparison.Ordinal);
        //     var insert = text2.Insert(index, text);
        //
        //     File.WriteAllText(calssePath, insert);
        //
        //     Debug.LogError("脚本已存在，重更新成功");
        // }
        // else
        // {
        File.WriteAllText(calssePath, code.ToString());

        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
    }

    private void OnDisable()
    {
        if (editor != null)
        {
            MethodInfo methodInfo = editor.GetType().GetMethod("OnDisable", BindingFlags.NonPublic | BindingFlags.Instance);
            methodInfo.Invoke(editor, null);
            UnityEditor.Editor.DestroyImmediate(editor);
        }

        editor = null;
    }
}
// }