#if UNITY_EDITOR
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;

namespace FutureEditor
{
    public class MVCBuildWindow : EditorWindow
    {
        private static string mvcClassName;     //mvc 模块名
        private static string fguiPackageName;     //FGUI 包名
        private static string fguiCompName;     //FGUI 组建名
        private static string foldePath;
        static string mvcRootPath = "/BingoBrain/ModuleUI/";  //创建MVC模块的目录

        [MenuItem("Jarvis/MVC/创建MVC代码模板", false, 0)]
        private static void ShowWindow()
        {
            MVCBuildWindow window = GetWindow<MVCBuildWindow>(true, "创建MVC代码模板窗口");
            window.minSize = new Vector2(280f, 170f);
            window.maxSize = window.minSize;
            window.Show();
        }

        private void OnGUI()
        {
            EditorGUILayout.Space();
            EditorGUILayout.BeginVertical();

            GUILayout.Space(5);
            GUILayout.BeginHorizontal();
            GUILayout.Label("MVC模块名:");
            mvcClassName = EditorGUILayout.TextField(mvcClassName, GUILayout.Height(20));
            GUILayout.EndHorizontal();
            GUILayout.Space(10);
            GUILayout.BeginHorizontal();
            GUILayout.Label("FGUI包名:");
            fguiPackageName = EditorGUILayout.TextField(fguiPackageName, GUILayout.Height(20));
            GUILayout.EndHorizontal();
            GUILayout.Space(10);
            GUILayout.BeginHorizontal();
            GUILayout.Label("FGUI组件名:");
            fguiCompName = EditorGUILayout.TextField(fguiCompName, GUILayout.Height(20));
            GUILayout.EndHorizontal();
            GUILayout.Space(10);
            if (GUILayout.Button("创建", GUILayout.Height(25)))
            {
                CreateMVC(mvcClassName);
            }
            EditorGUILayout.EndVertical();
        }

        private static void CreateMVC(string mvcName)
        {
            if (!string.IsNullOrEmpty(mvcName))
            {
                string mvcPath = mvcRootPath + mvcName;
                foldePath = Application.dataPath + mvcPath;
                if (Directory.Exists(foldePath))
                {
                    Debug.LogError("[MVCBuildWindow]Folde is exist!!!: " + foldePath);
                    Debug.LogError("[MVCBuildWindow]Create MVC Fail:" + mvcName);
                    return;
                }
                Directory.CreateDirectory(foldePath);

                CreateModel(mvcName);
                CreateUI(mvcName);
                CreateCtrl(mvcName);
                CreateUICtrl(mvcName);
                RegisterModule(mvcName);

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

                SelectObject("Assets/" + mvcPath);
                Debug.Log("[MVCBuildWindow]创建MVC代码模板完成");
            }
        }

        private static void SelectObject(string path)
        {
            Object obj = AssetDatabase.LoadMainAssetAtPath(path);
            if (obj == null) return;

            EditorGUIUtility.PingObject(obj);
            Selection.activeObject = obj;
        }

        private static void CreateModel(string className)
        {
            string modelClassStr =
@"using BingoBrain.Core;

namespace BingoBrain
{
    public class #ClassName#Model : BaseModel
    {
        #region 生命周期

        protected override void OnInit()
        {
        }

        protected override void OnDispose()
        {
        }

        protected override void OnReset()
        {
        }

        #endregion
    }
}";

            string replaceClassName = "#ClassName#";
            modelClassStr = modelClassStr.Replace(replaceClassName, className);
            string targetPath = foldePath + "/" + className + "Model.cs";
            File.WriteAllText(targetPath, modelClassStr, new UTF8Encoding(false));
        }

        private static void CreateUI(string className)
        {
            string uiClassStr =
@"using BingoBrain.Core;
using BingoBrain.HotFix;
using FGUI.ACommon;
using UnityEngine;

namespace BingoBrain
{
    public class #ClassName#UI : BaseUI
    {
        private #ClassName#UICtrl ctrl;
        private #ClassName#Model model;
        private FGUI.#PackageName#.#CompName# ui;

        public #ClassName#UI(#ClassName#UICtrl ctrl) : base(ctrl)
        {
            uiName = UIConst.#ClassName#UI;
            this.ctrl = ctrl;
        }

        protected override void SetUIInfo(UIInfo uiInfo)
        {
            uiInfo.packageName = ""#PackageName#"";
            uiInfo.assetName = ""#CompName#"";
            uiInfo.layerType = UILayerType.Normal;
            uiInfo.isNeedOpenAnim = false;
            uiInfo.isNeedCloseAnim = false;
            uiInfo.isNeedUIMask = true;
        }

        #region 生命周期
        protected override void OnInit()
        {
            //model = ModuleManager.Instance.GetModel(ModelConst.#ClassName#Model) as #ClassName#Model;
        }

        protected override void OnClose()
        {
        }

        protected override void OnBind()
        {
            ui = baseUI as FGUI.#PackageName#.#CompName#;
        }

        protected override void OnOpenBefore(object args)
        {
            InitView();
        }

        protected override void OnOpen(object args)
        {
        }

        protected override void OnHide()
        {
        }

        protected override void OnDisplay(object args)
        {
        }
        #endregion

        #region 消息
        protected override void AddListener()
        {
            
        }
        protected override void RemoveListener()
        {
            
        }
        #endregion

        //初始化页面逻辑
        private void InitView()
        {

        }
    }
}";
            string replacePackageName = "#PackageName#";
            uiClassStr = uiClassStr.Replace(replacePackageName, fguiPackageName);
            string replaceCompName = "#CompName#";
            uiClassStr = uiClassStr.Replace(replaceCompName, fguiCompName);
            string replaceClassName = "#ClassName#";
            uiClassStr = uiClassStr.Replace(replaceClassName, className);
            string targetPath = foldePath + "/" + className + "UI.cs";
            File.WriteAllText(targetPath, uiClassStr, new UTF8Encoding(false));
        }

        private static void CreateCtrl(string className)
        {
            string ctrlClassStr =
@"using BingoBrain.Core;

namespace BingoBrain
{
    public class #ClassName#Ctrl : BaseCtrl
    {
        public static #ClassName#Ctrl Instance { get; private set; }

        private #ClassName#Model model;

        #region 生命周期
        protected override void OnInit()
        {
            Instance = this;
            //model = ModuleManager.Instance..GetModel(ModelConst.#ClassName#Model) as #ClassName#Model;
        }

        protected override void OnDispose()
        {
            Instance = null;
        }

        #endregion
    }
}";

            string replaceClassName = "#ClassName#";
            ctrlClassStr = ctrlClassStr.Replace(replaceClassName, className);
            string targetPath = foldePath + "/" + className + "Ctrl.cs";
            File.WriteAllText(targetPath, ctrlClassStr, new UTF8Encoding(false));
        }

        private static void CreateUICtrl(string className)
        {
            string uiCtrlClassStr =
@"using BingoBrain.Core;
using BingoBrain.HotFix;

namespace BingoBrain
{
    public class #ClassName#UICtrl : BaseUICtrl
    {
        private #ClassName#UI ui;
        private #ClassName#Model model;

        private uint openUIMsg = SkinInfo.#ClassName#UI_Open;
        private uint closeUIMsg = SkinInfo.#ClassName#UI_Close;

        #region 生命周期
        protected override void OnInit()
        {
            //model = ModuleManager.Instance.GetModel(ModelConst.#ClassName#Model) as #ClassName#Model;
        }

        protected override void OnDispose()
        {
        }

        public override void OpenUI(object args = null)
        {
            if (ui == null)
            {
                ui = new #ClassName#UI(this);
                ui.Open(args);
            }
        }

        public override void CloseUI(object args = null)
        {
            if (ui != null && !ui.isClose)
            {
                ui.Close();
            }
            ui = null;
        }
        #endregion

        #region 消息
        public override uint GetOpenUIMsg(string uiName)
        {
            return openUIMsg;
        }
        public override uint GetCloseUIMsg(string uiName)
        {
            return closeUIMsg;
        }

        protected override void AddListener()
        {
            uiCtrlDispatcher.AddListener(openUIMsg, OpenUI);
            uiCtrlDispatcher.AddListener(closeUIMsg, CloseUI);
        }
        protected override void RemoveListener()
        {
            uiCtrlDispatcher.RemoveListener(openUIMsg, OpenUI);
            uiCtrlDispatcher.RemoveListener(closeUIMsg, CloseUI);
        }

        protected override void AddServerListener()
        {

        }
        protected override void RemoveServerListener()
        {

        }
        #endregion
    }
}";

            string replaceClassName = "#ClassName#";
            uiCtrlClassStr = uiCtrlClassStr.Replace(replaceClassName, className);
            string targetPath = foldePath + "/" + className + "UICtrl.cs";
            File.WriteAllText(targetPath, uiCtrlClassStr, new UTF8Encoding(false));
        }

        //测试
        // [MenuItem("Jarvis/MVC/RegisterModuleXXX", false, 0)]
        // static void RegisterModuleXXX(){
        //     RegisterModule("mmm");
        //     AssetDatabase.SaveAssets();
        //     AssetDatabase.Refresh();
        // }

        //注册模块
        static void RegisterModule(string name){
            //模块管理路径以及相关文件路径
            string moduleMngRootPath = Application.dataPath + "/BingoBrain/ModuleBoard/"; 
            string ctrlPath = moduleMngRootPath + "CtrlConst.cs";
            string modelPath = moduleMngRootPath + "ModelConst.cs";
            string uiConstPath = moduleMngRootPath + "UIConst.cs";
            string uiCtrlPath = moduleMngRootPath + "UICtrlConst.cs";
            string moduleMngPath = moduleMngRootPath + "ModuleBoard.cs";
            string UICtrlMsgPath = Application.dataPath + "/BingoBrain/Model/Info/SkinInfot.cs";

            //注册模块的常量
            InsertString(ctrlPath, $"\tpublic const string {name}Ctrl = \"{name}Ctrl\";\n\t");
            InsertString(modelPath, $"\tpublic const string {name}Model = \"{name}Model\";\n\t");
            InsertString(uiConstPath, $"\tpublic const string {name}UI = \"{name}UI\";\n\t");
            InsertString(uiCtrlPath, $"\tpublic const string {name}UICtrl = \"{name}UICtrl\";\n\t");
            
            //在模块类注册新模块
            InsertStringBeforeCharIndex(moduleMngPath, 0, $"\tmoduleBoardk.AddModel(ModelConst.{name}Model, new {name}Model());\n\t\t");
            InsertStringBeforeCharIndex(moduleMngPath, 1, $"\tmoduleBoardk.AddUIType(UIConst.{name}UI, typeof({name}UI));\n\t\t");
            InsertStringBeforeCharIndex(moduleMngPath, 2, $"\tmoduleBoardk.AddCtrl(CtrlConst.{name}Ctrl, new {name}Ctrl());\n\t\t");
            InsertStringBeforeCharIndex(moduleMngPath, 3, $"\tmoduleBoardk.AddUICtrl(UICtrlConst.{name}UICtrl, new {name}UICtrl());\n\t\t");
        
            InsertString(UICtrlMsgPath, $"\tpublic static uint {name}UI_Open = ++cursor_OpenClose;\n\t\tpublic static uint {name}UI_Close = ++cursor_OpenClose;\n\t");
        }

        static void InsertString(string path, string str){
            string f = File.ReadAllText(path);
            int index = f.IndexOf('}');
            f = f.Insert(index, str);
            File.WriteAllText(path, f);
        }

        static void InsertStringBeforeCharIndex(string path, int charIndex, string str){
            string f = File.ReadAllText(path);
            int indexCount = 0;
            int index = -1;
            for (int i = 0; i < f.Length; i++)
            {
                char c = f[i];
                if (c == '}' ){
                    if (indexCount == charIndex){
                        index = i;
                        break;
                    }
                    else{
                        indexCount++;
                    }
                }
            }
            if (index != -1){
                f = f.Insert(index, str);
                File.WriteAllText(path, f);
            }
        }
    }
}
#endif