using Thousandto.Code.Logic;
using Thousandto.Core.Asset;
using Thousandto.SkillEditor;
using Thousandto.SkillEditor.DIY;
using Thousandto.SkillEditor.Support;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;

namespace Thousandto.SkillEditor.DIY
{
    public class SkillEditor : EditorWindow
    {
        #region//入口
        [MenuItem("Ares/SkillEditor")]
        static void OpenSkillEditor()
        {
            var curScenes = EditorBuildSettings.scenes;
            var needSet = true;
            var allScenes = new List<EditorBuildSettingsScene>();
            for (int i = 0; i < curScenes.Length; ++i)
            {
                allScenes.Add(new EditorBuildSettingsScene(curScenes[i].path, true));
                if (curScenes[i].path == "Assets/SkillEditor/EditorRes/Scene/EditorScene.unity")
                {
                    needSet = false;
                }
            }
            if (needSet)
            {
                allScenes.Add(new EditorBuildSettingsScene("Assets/SkillEditor/EditorRes/Scene/EditorScene.unity", true));
                EditorBuildSettings.scenes = allScenes.ToArray();
                EditorUtility.DisplayDialog("提示", "自动将EditorScene场景添加到BuildSetting,请重新启动!", "确定");
                EditorApplication.isPlaying = false;
                return;
            }

            if (!EditorApplication.isPlaying)
            {
                EditorUtility.DisplayDialog("提示", "播放状态下才能打开技能编辑器!", "确定");
                return;
            }

            SkillResPathEditor.InitResPath();
            var win = (SkillEditor)EditorWindow.GetWindow(typeof(SkillEditor), true);
            win.wantsMouseMove = true;
            win.minSize = new Vector2(1860, 960);
            win.maxSize = new Vector2(1860, 960);
            win.Show();
            win.Init();
            IsOpen = true;
        }
        #endregion

        #region//界面渲染
        bool OnEditorModeGUI()
        {
            SkillEditorScene.OnGUI();

            bool isLeftMouseDown = false;
            bool isRightMouseUP = false;
            switch (Event.current.type)
            {
                case EventType.ScrollWheel:
                    {
                        if (_buttomRect.Contains(Event.current.mousePosition))
                        {
                            float oldScale = _curFrameWidthScale;
                            _curFrameWidthScale -= Event.current.delta.y * 0.05f;
                            if (_curFrameWidthScale > FrameWidthMaxScale)
                            {
                                _curFrameWidthScale = FrameWidthMaxScale;
                            }
                            if (_curFrameWidthScale < FrameWidthMinScale)
                            {
                                _curFrameWidthScale = FrameWidthMinScale;
                            }
                        }
                    }
                    break;
                case EventType.MouseDown:
                    {
                        if (_buttomRect.Contains(Event.current.mousePosition))
                        {
                            if (Event.current.button == 0)
                            {
                                //左键
                                isLeftMouseDown = true;
                                _draging = true;
                            }
                            else if (Event.current.button == 1)
                            {
                                //右键
                                isRightMouseUP = false;
                            }
                        }
                        if (SkillEventEditor.IsOpen)
                        {
                            SkillEventEditor.Hide();
                        }
                    }
                    break;
                case EventType.MouseUp:
                    {
                        if (Event.current.button == 0)
                        {
                            //左键
                            isLeftMouseDown = false;
                            _curDragEvent = null;
                            _draging = false;
                        }
                        else if (Event.current.button == 1)
                        {
                            //右键
                            if (_buttomRect.Contains(Event.current.mousePosition))
                            {
                                isRightMouseUP = true;
                            }
                        }
                    }
                    break;
            }

            #region//左侧操作面板
            GUILayout.BeginArea(_leftRect);
            EditorGUILayout.BeginHorizontal();
            if (GUILayout.Button("载入", GUILayout.Width(60)))
            {
                SkillEditorData.Load();
                Init();
            }
            bool bSave = false;
            if (GUILayout.Button("保存", GUILayout.Width(60)))
            {
                bSave = true;
            }

            if (GUILayout.Button("新技能", GUILayout.Width(60)))
            {
                SkillCreateAndChangeEditor.OpenCreate(this);
            }
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginVertical();
            GUILayout.Space(20);
            GUILayout.Label("筛选技能");
            EditorGUILayout.BeginHorizontal();
            if (SkillFilterEditor.FilterKeys != null)
            {
                var newSelect = EditorGUILayout.Popup(_selectFilter, SkillFilterEditor.FilterKeys, GUILayout.Width(100));
                if (newSelect != _selectFilter)
                {
                    _limitSkillName = SkillFilterEditor.GetFilterText(SkillFilterEditor.FilterKeys[newSelect]);
                    _selectFilter = newSelect;
                    ResetSkillList(_limitSkillName);
                    SetSelectSkill(_curSelectSkillName);
                }
            }
            if (GUILayout.Button("编辑筛选器", GUILayout.Width(90), GUILayout.Height(16)))
            {
                SkillFilterEditor.Open();
            }
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            string tmpFindName = EditorGUILayout.TextField(_limitSkillName, GUILayout.Width(180));
            if (_limitSkillName != tmpFindName)
            {
                ResetSkillList(tmpFindName);
                SetSelectSkill(_curSelectSkillName);
            }
            if (GUILayout.Button("X", GUILayout.Width(16), GUILayout.Height(16)))
            {
                ResetSkillList("");
                SetSelectSkill(_curSelectSkillName);
            }
            EditorGUILayout.EndHorizontal();

            GUILayout.Label("技能列表");
            if (_showSkillList.Count > 0)
            {
                int nowSelect = EditorGUILayout.Popup(_curSelectSkillIndex, _showSkillList.ToArray(), GUILayout.Width(200));
                if (nowSelect != _curSelectSkillIndex)
                {
                    //刷新界面
                    SetSelectSkill(_showSkillList[nowSelect]);
                    _curSelectSkillIndex = nowSelect;
                }
            }
            else
            {
                GUILayout.Label("没有符合筛选文本的技能!");
            }
            GUILayout.Space(50);

            var curSkill = SkillEditorData.FindSkill(_curSelectSkillName);
            if (curSkill != null)
            {
                EditorGUILayout.BeginHorizontal();
                GUILayout.Label("技能名字", GUILayout.Width(90));
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.TextField(curSkill.Name, GUILayout.Width(160));
                if (GUILayout.Button("修改", GUILayout.Width(36)))
                {
                    SkillCreateAndChangeEditor.OpenChange(this, curSkill);
                }
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.BeginHorizontal();
                GUILayout.Label("是否是召唤对象", GUILayout.Width(110));
                curSkill.IsSkillObject = EditorGUILayout.Toggle(curSkill.IsSkillObject, GUILayout.Width(20));
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.BeginHorizontal();
                GUILayout.Label("受击效果对玩家有效", GUILayout.Width(110));
                curSkill.IsPlayerValid = EditorGUILayout.Toggle(curSkill.IsPlayerValid, GUILayout.Width(20));
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.BeginHorizontal();
                GUILayout.Label("结束清除特效", GUILayout.Width(110));
                curSkill.EndClearVfx = EditorGUILayout.Toggle(curSkill.EndClearVfx, GUILayout.Width(20));
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.BeginHorizontal();
                GUILayout.Label("等待服务器返回后再执行", GUILayout.Width(110));
                curSkill.WaitServerResult = EditorGUILayout.Toggle(curSkill.WaitServerResult, GUILayout.Width(20));
                EditorGUILayout.EndHorizontal();

                if (GUILayout.Button("复制技能", GUILayout.Width(200), GUILayout.Height(20)))
                {
                    CopySkill(curSkill);
                }

                if (GUILayout.Button("删除技能", GUILayout.Width(200)))
                {
                    DeleteSkill(curSkill.Name);
                    EditorGUILayout.EndVertical();
                    GUILayout.EndArea();
                    return true;
                }
            }
            EditorGUILayout.EndVertical();
            GUILayout.EndArea();

            if(bSave)
            {
                SkillEditorData.Save();
                SkillEditorData.SaveBinary();
            }
            #endregion

            #region//下侧播放面板
            if (curSkill != null)
            {
                GUILayout.BeginArea(_buttomRect);
                EditorGUILayout.BeginHorizontal();
                curSkill.FrameCount = EditorGUILayout.IntField("技能帧数", curSkill.FrameCount, GUILayout.Width(200));
                GUILayout.Space(30);
                if (GUILayout.Button("播放", GUILayout.Width(100)))
                {
                    if (Application.isPlaying)
                    {
                        SkillEditorScene.UseSkill(curSkill);
                        //SkillEditorPlayerUI.PlaySkill(curSkill.Name);
                    }
                    else
                    {
                        EditorUtility.DisplayDialog("提示", "在Unity播放模式下才能使用技能播放功能", "确定");
                    }
                }

                GUILayout.Space(30);
                GUILayout.Label("显示走跑动作对比", GUILayout.Width(110));
                _showPauseContrast =  EditorGUILayout.Toggle(_showPauseContrast, GUILayout.Width(30));

                GUILayout.Space(30);
                GUILayout.Label("显示技能范围", GUILayout.Width(110));
                EditorBaseObject.ShowSkillRange = EditorGUILayout.Toggle(EditorBaseObject.ShowSkillRange, GUILayout.Width(30));
                EditorGUILayout.EndHorizontal();

                _scrollPos = GUILayout.BeginScrollView(_scrollPos, true, false, GUILayout.Width(1820));
                int drawFrameCount = Math.Max(PageFrameCount, curSkill.FrameCount);
                var spaceCount = (int)(CurFrameWidth * drawFrameCount);
                GUILayout.Box("", GUILayout.Width(spaceCount + 30));

                Vector2 size = new Vector2(2, 50);
                Vector2 pos = Vector2.zero;
                Rect boxRect = new Rect();
                Rect textRect = new Rect();
                textRect.size = new Vector2(30, 20);
                GUIStyle textStyle = new GUIStyle();

                textStyle.alignment = TextAnchor.MiddleCenter;

                GUIStyle eventStyle = new GUIStyle();
                eventStyle.alignment = TextAnchor.MiddleCenter;
                eventStyle.fontSize = 10;

                float frontY = 0f;
                int frontEventIndex = 0;
                int diffIndex = Mathf.RoundToInt(24f / CurFrameWidth);
                bool isShowEventMenu = false;
                for (int i = 0; i < drawFrameCount; ++i)
                {
                    pos.x = i * CurFrameWidth + 10;
                    textRect.position = new Vector2(pos.x - 15, 0);

                    if (i % 5 == 0)
                    {
                        GUI.Label(textRect, i.ToString(), textStyle);
                        boxRect.size = new Vector2(2, 240);
                        pos.y = 20;
                        boxRect.position = pos;
                    }
                    else
                    {
                        pos.y = 25;
                        boxRect.size = new Vector2(2, 230);
                        boxRect.position = pos;
                    }

                    if (i < curSkill.FrameCount)
                    {
                        GUI.color = Color.white;
                    }
                    else
                    {
                        GUI.color = Color.black;
                    }
                    GUI.Box(boxRect, string.Empty);


                    var eventList = curSkill.FindEventByFrame(i);
                    boxRect.size = new Vector2(24, 16);

                    if (i - frontEventIndex >= diffIndex)
                    {
                        frontY = 0;
                    }

                    int j = 0;
                    for (; j < eventList.Count; ++j)
                    {
                        GUI.color = Color.white;
                        boxRect.position = new Vector2(i * CurFrameWidth, frontY + 25 + j * 18);
                        frontEventIndex = i;

                        if (isLeftMouseDown && boxRect.Contains(Event.current.mousePosition))
                        {
                            _curDragEvent = eventList[j];
                        }
                        if (SkillEventEditor.IsOpen && SkillEventEditor.EventInfo == eventList[j])
                        {
                            GUI.color = Color.red;
                        }
                        if (GUI.Button(boxRect, GetEventName(eventList[j].EventType)))
                        {
                            if (isRightMouseUP)
                            {
                                _curDragEvent = null;
                                if (!isShowEventMenu)
                                {
                                    var mousePos = Event.current.mousePosition;
                                    _skillEventGo.name = string.Format("edit;{0};{1}", curSkill.Name, eventList[j].EventID);
                                    EditorUtility.DisplayPopupMenu(new Rect(mousePos.x, mousePos.y, 0, 0), "CONTEXT/SkillEvent/", new MenuCommand(_skillEventGo));
                                    isShowEventMenu = true;
                                }
                            }
                            else
                            {
                                //连续两次点击,打开编辑界面
                                SkillEventEditor.Open(eventList[j]);
                            }
                        }
                    }
                    GUI.color = Color.white;
                    frontY += j * 18;

                    pos.x -= (CurFrameWidth / 2 - 4);
                    boxRect.position = pos;
                    boxRect.size = new Vector2(CurFrameWidth, 200);
                    if (_draging && boxRect.Contains(Event.current.mousePosition))
                    {
                        _curSelectFrame = i;
                        if (_curDragEvent != null && i < curSkill.FrameCount)
                        {
                            _curDragEvent.EventFrame = i;
                        }
                        SkillEditorScene.DoPauseAnim(curSkill, _curSelectFrame, _showPauseContrast);
                    }

                    if (isRightMouseUP && boxRect.Contains(Event.current.mousePosition) && i < curSkill.FrameCount)
                    {
                        if (!isShowEventMenu)
                        {
                            var mousePos = Event.current.mousePosition;
                            _skillEventGo.name = string.Format("create;{0};{1}", curSkill.Name, i);
                            EditorUtility.DisplayPopupMenu(new Rect(mousePos.x, mousePos.y, 0, 0), "CONTEXT/SkillEvent/", new MenuCommand(_skillEventGo));
                            isShowEventMenu = true;
                        }
                    }
                }

                if (SkillEditorScene.LocalUser != null && SkillEditorScene.LocalUser.SkillManager.IsUsing && SkillEditorScene.LocalUser.SkillManager.CurSkill != null)
                {
                    _curSelectFrame = SkillEditorScene.LocalUser.SkillManager.CurSkill.CurFrame;
                    if(SkillEditorScene.LocalUser.SkillManager.CurSkill.VisualInfo != curSkill)
                    {
                        curSkill = SkillEditorScene.LocalUser.SkillManager.CurSkill.VisualInfo;
                    }
                }
                GUI.color = Color.red;
                boxRect.position = new Vector2(_curSelectFrame * CurFrameWidth + 10, 0);
                boxRect.size = new Vector2(2, 280);
                GUI.Box(boxRect, string.Empty);
                GUI.color = Color.white;
                GUILayout.EndScrollView();
                GUILayout.EndArea();
            }
            #endregion

            #region//右侧操作面板
            GUILayout.BeginArea(_rightRect);
            EditorGUILayout.BeginVertical();
            SkillEditorPlayerUI.OnGUI();
            EditorGUILayout.EndVertical();
            GUILayout.EndArea();
            #endregion

            return true;
        }

        void OnGUI()
        {
            if (OnEditorModeGUI())
            {
                Repaint();
            }
        }

        private void Update()
        {
            if (Application.isPlaying)
            {
                AudioPlayer.Update();
                EditorVFXPlayer.Instance.Update();
                SkillEditorScene.Update();
            }
            else
            {
                Close();
            }
        }
        #endregion

        #region//私有变量
        private const float FrameWidthMaxScale = 1f;
        private const float FrameWidthMinScale = 0.3f;
        private Rect _leftRect = new Rect(10, 0, 200, 600);
        private Rect _rightRect = new Rect(1650, 0, 200, 800);
        private Rect _buttomRect = new Rect(10, 720, 1820, 240);
        private float _curFrameWidthScale = 1f;
        private int _curSelectFrame = 0;

        private List<string> _showSkillList = new List<string>();
        private int _curSelectSkillIndex = 0;
        private string _curSelectSkillName = string.Empty;
        private string _limitSkillName = string.Empty;
        private SkillBaseEventInfo _curDragEvent = null;
        private bool _draging = false;
        private bool _frontPlayingState = false;
        private float _sliderValue = 0f;
        private const int PageFrameCount = 301;
        private Vector2 _scrollPos = Vector2.zero;
        private GameObject _skillEventGo = null;
        private int _selectFilter = 0;
        private bool _showPauseContrast = false;
        #endregion

        #region//属性
        private float CurFrameWidth
        {
            get
            {
                return _curFrameWidthScale * 20;
            }
        }
        public string CurSelectSkillName
        {
            get
            {
                return _curSelectSkillName;
            }
        }

        public static bool IsOpen { get; private set; }
        #endregion

        #region//私有函数
        //初始化
        private void Init()
        {
            SkillFilterEditor.Init();
            SkillEditorScene.Load();
            _curFrameWidthScale = FrameWidthMaxScale;
            _curSelectFrame = 0;
            SkillEditorData.Load();
            _limitSkillName = string.Empty;
            ResetSkillList(_limitSkillName);
            SetSelectSkill(string.Empty);
            _draging = false;
            _skillEventGo = new GameObject("SkillEditorTmp");
            GameObject.DontDestroyOnLoad(_skillEventGo);
        }

        //创建新技能
        public bool CreateNewSkill(string name)
        {
            if (SkillEditorData.CreateNewSkill(name))
            {
                _showSkillList.Add(name);
                SetSelectSkill(name);
                Repaint();
                return true;
            }
            else
            {
                return false;
            }
        }
        //删除技能
        private void DeleteSkill(string name)
        {
            SkillEditorData.RemoveSkill(name);
            ResetSkillList(_limitSkillName);
            if (_showSkillList.Count <= 0)
            {
                //如果当前查找选项里边已经没有技能了,清空查找选项重新查找
                ResetSkillList(string.Empty);
            }
            SetSelectSkill(string.Empty);
        }
        //复制技能
        private void CopySkill(SkillVisualInfo skill)
        {
            var name = SkillEditorData.CopyNewSkill(skill);
            _showSkillList.Add(name);
            SetSelectSkill(name);
        }
        //修改名字
        public bool ChangeSkillName(SkillVisualInfo skill, string newName)
        {
            for (int i = 0; i < SkillEditorData.SkillList.Count; ++i)
            {
                if (SkillEditorData.SkillList[i].Name == newName)
                {
                    return false;
                }
            }
            for (int i = 0; i < _showSkillList.Count; ++i)
            {
                if (_showSkillList[i] == skill.Name)
                {
                    _showSkillList[i] = newName;
                }
            }
            if (_curSelectSkillName == skill.Name)
            {
                _curSelectSkillName = newName;
            }
            skill.Name = newName;
            Repaint();
            return true;
        }

        string GetEventName(SkillEventDefine type)
        {
            string result = "None";
            switch (type)
            {
                case SkillEventDefine.PlayAnimation:
                    result = "A";
                    break;
                case SkillEventDefine.PlayVfx:
                    result = "V";
                    break;
                case SkillEventDefine.PlaySfx:
                    result = "S";
                    break;
                case SkillEventDefine.PlayCameraShake:
                    result = "K";
                    break;
                case SkillEventDefine.PlayBlur:
                    result = "B";
                    break;
                case SkillEventDefine.PlaySlow:
                    result = "L";
                    break;
                case SkillEventDefine.PlayLockTrajectory:
                    result = "lt";
                    break;
                case SkillEventDefine.DisableMove:
                    result = "dr";
                    break;
                case SkillEventDefine.DisableChangeDir:
                    result = "dc";
                    break;
                case SkillEventDefine.PlaySimpleSkillObject:
                    result = "so";
                    break;
                case SkillEventDefine.PlaySkillObject:
                    result = "O";
                    break;
                case SkillEventDefine.PlayHit:
                    result = "H";
                    break;
                case SkillEventDefine.PlaySelfMove:
                    result = "M";
                    break;
                case SkillEventDefine.PlayHideWeapon:
                    result = "W";
                    break;
                case SkillEventDefine.PlayLinkDamage:
                    result = "L";
                    break;
            }
            return result;
        }

        public void OnDestroy()
        {
            IsOpen = false;
            GameObject.DestroyImmediate(_skillEventGo, true);
            SkillEventEditor.Hide();
            SkillCreateAndChangeEditor.Hide();
            SkillFilterEditor.Hide();
            SkillEditorScene.UnLoad();
        }
        #endregion

        #region//公有函数
        //重新设置技能列表
        public void ResetSkillList(string nameLimit)
        {
            _limitSkillName = nameLimit;
            var skillList = SkillEditorData.SkillList;
            _showSkillList.Clear();
            for (int i = 0; i < skillList.Count; ++i)
            {
                if (string.IsNullOrEmpty(nameLimit) || skillList[i].Name.IndexOf(nameLimit) >= 0)
                {
                    _showSkillList.Add(skillList[i].Name);
                }
            }
        }

        //设置选择的技能
        public void SetSelectSkill(string skillName)
        {
            _curDragEvent = null;
            SkillEventEditor.Hide();
            if (_showSkillList.Count > 0)
            {
                _curSelectSkillIndex = 0;
                _curSelectSkillName = _showSkillList[0];
            }

            for (int i = 0; i < _showSkillList.Count; ++i)
            {
                if (_showSkillList[i] == skillName)
                {
                    _curSelectSkillIndex = i;
                    _curSelectSkillName = skillName;
                }
            }
        }
        #endregion
    }
}