using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Diagnostics;
using System.Text;
using System.Windows.Forms;
using System.IO;
using CommonAI.Zone;
using CommonFroms.Utils;
using CommonAI.Zone.ZoneEditor;
using CommonLang.Xml;
using System.Xml;
using CommonAIEditor.Plugins.Win32;
using CommonLang.IO;
using CommonAI.Zone.Attributes;
using CommonLang.File;
using System.Threading;
using GameEditorPlugin.Utils;
using CommonLang;
using CommonLang.Property;
using CommonLang.Concurrent;
using CommonAIEditor.Scene;
using CommonAI.Zone.ZoneEditor.EventTrigger;
using CommonLang.Protocol;
using CommonLang.XCSV;
using GameEditorPlugin.Win32.Runtime;
using CommonAI.Zone.Replay;
using CommonAIEditor.EventEditor;
using CommonFroms.G2D;
using CommonFroms.G2D.DataGrid;

namespace CommonAIEditor
{
    public partial class Editor : Form
    {
        //------------------------------------------------------------------------------
        #region static_fields
        public static string EditorRootDir { get { return s_editroot.FullName; } }
        public static string EditorSettingDir { get { return s_proj_setting_root.FullName; } }
        public static string DataDir { get { return s_datadir.FullName; } }
        public static string DataDir_units { get { return Editor.DataDir + "/units"; } }
        public static string DataDir_skills { get { return Editor.DataDir + "/skills"; } }
        public static string DataDir_spells { get { return Editor.DataDir + "/spells"; } }
        public static string DataDir_buffs { get { return Editor.DataDir + "/buffs"; } }
        public static string DataDir_items { get { return Editor.DataDir + "/items"; } }
        public static string DataDir_unit_triggers { get { return Editor.DataDir + "/unit_triggers"; } }
        public static string DataDir_unit_events { get { return Editor.DataDir + "/unit_events"; } }
        public static string DataDir_scenes { get { return Editor.DataDir + "/scenes"; } }
        public static string ResDir { get { return s_resdir.FullName; } }
        public static Font EditorFont = new System.Drawing.Font(
                    "微软雅黑", 9F,
                    System.Drawing.FontStyle.Regular,
                    System.Drawing.GraphicsUnit.Point,
                    ((byte)(134)));

        public static Editor Instance { get { return s_instance; } }
        private static Editor s_instance;
        private static DirectoryInfo s_editroot;// GameEditor
        private static DirectoryInfo s_proj_setting_root;// GameEditor/.setting
        private static DirectoryInfo s_datadir;// GameEditor/data
        private static DirectoryInfo s_resdir;// GameEditor/res
        internal static void SetDataRoot(string root)
        {
            s_editroot = new DirectoryInfo(root);
            s_proj_setting_root = new DirectoryInfo(root + "\\.setting");
            s_datadir = new DirectoryInfo(root + "\\data");
            s_resdir = new DirectoryInfo(root + "\\res");
            DefaultResourceLoader.SetRoot(root);
        }
        #endregion
        //------------------------------------------------------------------------------
        #region fields
        private bool autoSave = false;
        private HashMap<Type, IDataManager> template_panels = new HashMap<Type, IDataManager>();
        private HashMap<TabPage, IDataManager> page_panels = new HashMap<TabPage, IDataManager>();
        private DataManagerPanel<UnitInfo> units;
        private DataManagerPanel<SkillTemplate> skills;
        private DataManagerPanel<SpellTemplate> spells;
        private DataManagerPanel<BuffTemplate> buffs;
        private DataManagerPanel<ItemTemplate> items;
        private DataManagerPanel<UnitTriggerTemplate> unit_triggers;
        private DataManagerPanel<UnitEventTemplate> unit_events;
        private DataManagerPanel<SceneData> scenes;

        public MessageFactoryGenerator MessageFactory { get { return TemplateManager.MessageCodec; } }


        public ImageList Icons
        {
            get { return imageList1; }
        }

        #endregion
        //------------------------------------------------------------------------------
        public Editor(bool autoSave = false)
        {
            InitializeComponent();
            Editor.s_instance = this;
            if (!s_proj_setting_root.Exists)
            {
                s_proj_setting_root.Create();
            }
            GameEditorPropertyAdapter.Init();
            this.autoSave = autoSave;
           
        }


        //-----------------------------------------------------------------------------------------------------------
        public Config CFG { get; private set; }
        public ICommonConfig ExtCFG { get; private set; }
        public TerrainDefinitionMap TerrainDefinition { get; private set; }
        public UnitActionDefinitionMap UnitActionDefinition { get; private set; }
        public FileInfo SaveCfgFile { get { return new FileInfo(Editor.DataDir + "/config.xml"); } }
        public FileInfo SaveCfgExtFile { get { return new FileInfo(Editor.DataDir + "/config_ext.xml"); } }
        public FileInfo SaveTerrainDefinitionFile { get { return new FileInfo(Editor.DataDir + "/terrain_definition.xml"); } }
        public FileInfo SaveUnitActionDefinition { get { return new FileInfo(Editor.DataDir + "/unit_action_definition.xml"); } }
        public TerrainDefinitionMap.MapBlockBrush DefaultTerrainBrush
        {
            get
            {
                foreach (var b in TerrainDefinition.Brushes)
                {
                    if (b.IsBlock)
                    {
                        return b;
                    }
                }
                return null;
            }
        }
        private void InitAllTempaltes()
        {

            this.units = new DataManagerPanel<UnitInfo>("单位",
                Editor.DataDir + "/units",
                Editor.EditorSettingDir + "/units",
                imageList1,
                "icons_tool_bar2.png",
                tabPageUnits.ImageKey);
            this.skills = new DataManagerPanel<SkillTemplate>("技能",
                Editor.DataDir + "/skills",
                Editor.EditorSettingDir + "/skills",
                imageList1,
                "icons_tool_bar2.png",
                tabPageSkills.ImageKey);
            this.spells = new DataManagerPanel<SpellTemplate>("法术",
               Editor.DataDir + "/spells",
               Editor.EditorSettingDir + "/spells",
               imageList1,
               "icons_tool_bar2.png",
               tabPageSpells.ImageKey);
            this.buffs = new DataManagerPanel<BuffTemplate>("BUFF",
                 Editor.DataDir + "/buffs",
                 Editor.EditorSettingDir + "/buffs",
                imageList1,
                "icons_tool_bar2.png",
                tabPageBuffs.ImageKey);
            this.items = new DataManagerPanel<ItemTemplate>("物品",
                 Editor.DataDir + "/items",
                 Editor.EditorSettingDir + "/items",
                imageList1,
                "icons_tool_bar2.png",
                tabPageItems.ImageKey);
            this.unit_triggers = new DataManagerPanel<UnitTriggerTemplate>("单位触发器",
                Editor.DataDir + "/unit_triggers",
                Editor.EditorSettingDir + "/unit_triggers",
               imageList1,
               "icons_tool_bar2.png",
               tabPageUnitTriggers.ImageKey);
            this.unit_events = new DataManagerPanel<UnitEventTemplate>("单位事件",
                Editor.DataDir + "/unit_events",
                Editor.EditorSettingDir + "/unit_events",
                imageList1,
                "icons_tool_bar2.png",
                tabPageUnitEvents.ImageKey);
            this.scenes = new DataManagerPanel<SceneData>("场景",
                Editor.DataDir + "/scenes",
                Editor.EditorSettingDir + "/scenes",
               imageList1,
               "icons_tool_bar2.png",
               tabPageScene.ImageKey);
            this.scenes.SetEnableDataGrid(false);

            tabPageUnits.Controls.Add(units);
            tabPageSkills.Controls.Add(skills);
            tabPageSpells.Controls.Add(spells);
            tabPageBuffs.Controls.Add(buffs);
            tabPageItems.Controls.Add(items);
            tabPageUnitTriggers.Controls.Add(unit_triggers);
            tabPageUnitEvents.Controls.Add(unit_events);
            tabPageScene.Controls.Add(scenes);

            //模板类型和DataManagerPanel映射关系//
            this.template_panels.Add(typeof(UnitInfo), units);
            this.template_panels.Add(typeof(SkillTemplate), skills);
            this.template_panels.Add(typeof(SpellTemplate), spells);
            this.template_panels.Add(typeof(BuffTemplate), buffs);
            this.template_panels.Add(typeof(ItemTemplate), items);
            this.template_panels.Add(typeof(UnitTriggerTemplate), unit_triggers);
            this.template_panels.Add(typeof(UnitEventTemplate), unit_events);
            this.template_panels.Add(typeof(SceneData), scenes);

            //TabPage和DataManagerPanel映射关系//
            this.page_panels.Add(tabPageUnits, units);
            this.page_panels.Add(tabPageSkills, skills);
            this.page_panels.Add(tabPageSpells, spells);
            this.page_panels.Add(tabPageBuffs, buffs);
            this.page_panels.Add(tabPageItems, items);
            this.page_panels.Add(tabPageUnitTriggers, unit_triggers);
            this.page_panels.Add(tabPageUnitEvents, unit_events);
            this.page_panels.Add(tabPageScene, scenes);

            //unit events//
            {
                ToolStripMenuItem open = new ToolStripMenuItem("单位事件编辑器");
                open.Size = new System.Drawing.Size(136, 22);
                open.Click += openUnitEvent_Click;
                unit_events.AddChildMenuItem(0, open);
                unit_events.AddChildMenuItem(1, new ToolStripSeparator());
                unit_events.GetTreeView().NodeMouseDoubleClick +=
                    new TreeNodeMouseClickEventHandler(openUnitEvent_Click);
            }

            //scene menu//
            {

                {
                    ToolStripMenuItem open_group = new ToolStripMenuItem("场景编辑器");
                    open_group.Size = new System.Drawing.Size(136, 22);
                    {
                        ToolStripMenuItem open_btn = new ToolStripMenuItem("打开(" + EditorPlugin.CurrentPlugin.Name + ")");
                        open_btn.Size = new System.Drawing.Size(136, 22);
                        open_btn.Click += new EventHandler(sceneBtn_OpenNode_Click);
                        open_group.DropDownItems.Add(open_btn);

                        ToolStripMenuItem open_win32 = new ToolStripMenuItem("打开(Win32)");
                        open_win32.Size = new System.Drawing.Size(136, 22);
                        open_win32.Click += new EventHandler(sceneBtn_OpenNodeWin32_Click);
                        open_group.DropDownItems.Add(open_win32);
                    }
                    scenes.AddChildMenuItem(0, open_group);
                }
                {
                    ToolStripMenuItem run_btn = new ToolStripMenuItem("运行");
                    run_btn.Size = new System.Drawing.Size(136, 22);

                    ToolStripMenuItem run_game = new ToolStripMenuItem("运行(" + EditorPlugin.CurrentPlugin.Name + ")");
                    run_game.Size = new System.Drawing.Size(136, 22);
                    run_game.Click += new EventHandler(sceneBtn_RunGAME_Click);
                    run_btn.DropDownItems.Add(run_game);

                    ToolStripMenuItem run_emu = new ToolStripMenuItem("运行(Win32)");
                    run_emu.Size = new System.Drawing.Size(136, 22);
                    run_emu.Click += new EventHandler(sceneBtn_RunEMU_Click);
                    run_btn.DropDownItems.Add(run_emu);

                    ToolStripMenuItem run_server = new ToolStripMenuItem("运行(Win32)服务器");
                    run_server.Size = new System.Drawing.Size(136, 22);
                    run_server.Click += new EventHandler(sceneBtn_RunEMUServer_Click);
                    run_btn.DropDownItems.Add(run_server);

                    run_btn.DropDownItems.Add(new ToolStripSeparator());

                    ToolStripMenuItem run_rec = new ToolStripMenuItem("运行并录制战报(Win32)");
                    run_rec.Size = new System.Drawing.Size(136, 22);
                    run_rec.Click += new EventHandler(sceneBtn_RunREC_Click);
                    run_btn.DropDownItems.Add(run_rec);

                    ToolStripMenuItem run_rec_play = new ToolStripMenuItem("播放战报(Win32)");
                    run_rec_play.Size = new System.Drawing.Size(136, 22);
                    run_rec_play.Click += new EventHandler(sceneBtn_LoadREC_Click);
                    run_btn.DropDownItems.Add(run_rec_play);

                    scenes.AddChildMenuItem(1, run_btn);
                }
                {
                    ToolStripMenuItem test_astar = new ToolStripMenuItem("测试寻路");
                    test_astar.Size = new System.Drawing.Size(136, 22);
                    test_astar.Click += new EventHandler(sceneBtn_TestAstar_Click);
                    scenes.AddChildMenuItem(2, test_astar);
                }
                {
                    scenes.AddChildMenuItem(3, new ToolStripSeparator());
                }
                scenes.GetTreeView().NodeMouseDoubleClick +=
                    new TreeNodeMouseClickEventHandler(sceneBtn_DoubleClickNode);
            }
            LoadDataTask task = new LoadDataTask();
            new G2DProgressDialog(task).ShowDialog(this);
        }

        //-----------------------------------------------------------------------------------------------------------

        public EditorTemplatesData GetEditorTemplatesData()
        {
            return new EditorTemplatesData(
                TerrainDefinition,
                UnitActionDefinition,
                    this.units.GetAllNodeData(),
                    this.skills.GetAllNodeData(),
                    this.spells.GetAllNodeData(),
                    this.buffs.GetAllNodeData(),
                    this.items.GetAllNodeData(),
                    this.unit_triggers.GetAllNodeData(),
                    this.unit_events.GetAllNodeData(),
                    this.scenes.GetAllNodeData());
        }
        public void RefreshAll()
        {
            this.units.RefreshData();
            this.skills.RefreshData();
            this.spells.RefreshData();
            this.buffs.RefreshData();
            this.items.RefreshData();
            this.unit_triggers.RefreshData();
            this.unit_events.RefreshData();
            this.scenes.RefreshData();
        }
        public void SaveEditorStatus()
        {
            foreach (var temp in template_panels.Values)
            {
                temp.SaveEditorStatus();
            }
        }

        //-----------------------------------------------------------------------------------------------------------
        #region _SaveLoad_
        //-----------------------------------------------------------------------------------------------------------

        private void loadCFG()
        {
            try
            {
                this.CFG = EditorTemplates.LoadXmlAs(SaveCfgFile.FullName, new Config());
                this.ExtCFG = EditorTemplates.LoadXmlAs(SaveCfgExtFile.FullName, TemplateManager.Factory.CreateCommonCFG());
                this.TerrainDefinition = EditorTemplates.LoadXmlAs(SaveTerrainDefinitionFile.FullName, new TerrainDefinitionMap());
                this.UnitActionDefinition = EditorTemplates.LoadXmlAs(SaveUnitActionDefinition.FullName, new UnitActionDefinitionMap());
            }
            catch (Exception err)
            {
                MessageBox.Show(err.Message);
            }
        }
        private static void saveCFG(object obj, FileInfo file)
        {
            try
            {
                string file1 = file.FullName;
                using (FileStream xmlfs = new FileStream(file1, FileMode.Create, FileAccess.Write))
                {
                    XmlUtil.SaveToXML(xmlfs, obj, true);
                }
            }
            catch (Exception err)
            {
                MessageBox.Show(err.Message);
            }
        }
        private void saveCFG()
        {
            saveCFG(this.CFG, SaveCfgFile);
            saveCFG(this.ExtCFG, SaveCfgExtFile);
            saveCFG(this.TerrainDefinition, SaveTerrainDefinitionFile);
            saveCFG(this.UnitActionDefinition, SaveUnitActionDefinition);
        }
        private void saveAll(bool check = false)
        {
            SaveDataTask task = new SaveDataTask(this, check);
            new G2DProgressDialog(task).ShowDialog(this);
        }
        private void sceneEditor_onSavedScene(SceneEditor editor, G2DTreeNode<SceneData> node)
        {
            scenes.SaveNode(node);

        }


        private class LoadDataTask : IProgress
        {
            private readonly Editor editor = Editor.Instance;
            private AtomicInteger mNodeProgress = new AtomicInteger(0);
            public LoadDataTask()
            {
                this.Title = "加载中...";
                this.Maximum =
                    editor.units.GetTryLoadCount() +
                    editor.skills.GetTryLoadCount() +
                    editor.spells.GetTryLoadCount() +
                    editor.buffs.GetTryLoadCount() +
                    editor.items.GetTryLoadCount() +
                    editor.unit_triggers.GetTryLoadCount() +
                    editor.unit_events.GetTryLoadCount() +
                    editor.scenes.GetTryLoadCount() +
                    0;
            }
            public override int Value
            {
                get
                {
                    return mNodeProgress.Value;
                }
            }
            public override void Run()
            {
                this.Text = "加载单位";
                editor.units.LoadAll(mNodeProgress);
                this.Text = "加载技能";
                editor.skills.LoadAll(mNodeProgress);
                this.Text = "加载法术";
                editor.spells.LoadAll(mNodeProgress);
                this.Text = "加载BUFF";
                editor.buffs.LoadAll(mNodeProgress);
                this.Text = "加载物品";
                editor.items.LoadAll(mNodeProgress);
                this.Text = "加载单位触发器";
                editor.unit_triggers.LoadAll(mNodeProgress);
                this.Text = "加载单位事件";
                editor.unit_events.LoadAll(mNodeProgress);
                this.Text = "加载场景";
                editor.scenes.LoadAll(mNodeProgress);
            }
            public override void Done()
            {
                editor.units.Refresh();
                editor.skills.Refresh();
                editor.spells.Refresh();
                editor.buffs.Refresh();
                editor.items.Refresh();
                editor.unit_triggers.Refresh();
                editor.unit_events.Refresh();
                editor.scenes.Refresh();
            }
        }

        private class SaveDataTask : IProgress
        {
            private bool check;
            private readonly Editor editor;
            private readonly EditorTemplatesData all_nodes;
            private readonly List<FileInfo> plugin_files;

            private string mState = "";
            private bool mIsDone = false;
            private AtomicInteger mNodeProgress = new AtomicInteger(0);
            private AtomicFloat mXLSProgress = new AtomicFloat(0);
            private AtomicFloat mPluginProgress = new AtomicFloat(0);
            private AtomicFloat mPluginCSVProgress = new AtomicFloat(0);
            private AtomicFloat mLanguageProgress = new AtomicFloat(0);
            private int mNodeMax = 0;
            private float mXLSMax = 0;


            public SaveDataTask(Editor editor, bool check)
            {
                this.check = check;
                this.editor = editor;
                this.all_nodes = editor.GetEditorTemplatesData();
                this.plugin_files = checkPlugins();
                this.mNodeMax = all_nodes.FileCount;
                this.mXLSMax = plugin_files.Count;
            }

            public override string Title
            {
                get { return "保存中..."; }
            }
            public override string Text
            {
                get { return mState; }
            }
            public override int Minimum
            {
                get { return 0; }
            }
            public override int Maximum
            {
                get
                {
                    return (int)(0
                        + (100f) // nodes 100%
                        + (100f * (CommonAIEditor.Program.g_SimpleGen ? 0 : 1)) // language 100%
                        + (10f) // plugins saving 100%
                        + (100f * mXLSMax) // plugins csv 100%
                        + (100f * mXLSMax) // xls 2 csv 100%
                        );
                }
            }
            public override int Value
            {
                get
                {
                    return (int)(0
                  + (100f * mNodeProgress.Value / mNodeMax)
                  + (100f * mLanguageProgress.Value)
                  + (100f * mPluginProgress.Value)
                  + (100f * mPluginCSVProgress.Value)
                  + (100f * mXLSProgress.Value)
                  );
                }
            }
            public override bool IsDone
            {
                get { return mIsDone; }
            }
            public override void Run()
            {
                mState = "生成序列号";
                new SerialMaker().Gen(all_nodes);
                List<FileInfo> gen_md5_files = new List<FileInfo>();
                // save all xml
                {
                    editor.saveCFG();
                    mState = "保存单位";
                    editor.units.SaveAll(mNodeProgress, check);
                    mState = "保存技能";
                    editor.skills.SaveAll(mNodeProgress, check);
                    mState = "保存法术";
                    editor.spells.SaveAll(mNodeProgress, check);
                    mState = "保存BUFF";
                    editor.buffs.SaveAll(mNodeProgress, check);
                    mState = "保存物品";
                    editor.items.SaveAll(mNodeProgress, check);
                    mState = "保存单位触发器";
                    editor.unit_triggers.SaveAll(mNodeProgress, check);
                    mState = "保存单位事件";
                    editor.unit_events.SaveAll(mNodeProgress, check);
                    mState = "保存场景";
                    editor.scenes.SaveAll(mNodeProgress, check);

					if (!CommonAIEditor.Program.g_SimpleGen)
					{
						mState = "生成语言文件";
						string language = EditorTemplates.GenLocalizationCsv(all_nodes, mLanguageProgress); // +=1
						File.WriteAllText(EditorRootDir + "\\language.csv", language, CUtils.UTF8);
					}
                  
                }
                // add base md5 files
                {
                    gen_md5_files.Add(editor.SaveCfgFile);
                    gen_md5_files.Add(editor.SaveCfgExtFile);
                    gen_md5_files.Add(editor.SaveTerrainDefinitionFile);
                    gen_md5_files.Add(editor.units.GetMd5File());
                    gen_md5_files.Add(editor.skills.GetMd5File());
                    gen_md5_files.Add(editor.spells.GetMd5File());
                    gen_md5_files.Add(editor.buffs.GetMd5File());
                    gen_md5_files.Add(editor.items.GetMd5File());
                    gen_md5_files.Add(editor.unit_triggers.GetMd5File());
                    gen_md5_files.Add(editor.unit_events.GetMd5File());
                    gen_md5_files.Add(editor.scenes.GetMd5File());
                }
                // save all game plugins
                try
                {
                    mState = "保存各游戏扩展插件:" + TemplateManager.Factory.GetType().Name;
                    TemplateManager.Factory.Formula.OnEditorSaving(
                        all_nodes,
                        new DirectoryInfo(DataDir),
                        gen_md5_files,
                        mPluginProgress); // += 1

                    List<XCSVMeta> xls2csv = new List<XCSVMeta>();
                    foreach (FileInfo xls in plugin_files)
                    {
                        mState = "生成插件数据:" + xls.Name;
                        XLS2XCSV csv = new XLS2XCSV(xls);
                        csv.Load(mXLSProgress); // += 1
                        savedPluginFileTimes.Put(xls.FullName, xls.LastWriteTime);
                        xls2csv.Add(csv.Meta);
                    }
                    mState = "解析插件数据:" + TemplateManager.Factory.GetType().Name;
                    TemplateManager.Factory.Formula.OnEditorPluginSaved(all_nodes, xls2csv, gen_md5_files, mPluginCSVProgress); // += 1

					mState = "生成资源版本号";
					genResourceVersion(gen_md5_files);
					if (new FileInfo("../../Http/ResBuilder.exe").Exists)
					{
						Process process = Process.Start(new ProcessStartInfo("cmd.exe", "/C ResBuilder.exe -np -!uires -!lua -!uiconvertbin")
						{
							CreateNoWindow = true,
							UseShellExecute = false,
							WorkingDirectory = "../../Http"
						});
						process.WaitForExit();
						process.Close();
					}
				}
                finally
                {
                    mState = "完成";
                    mIsDone = true;
                }
            }

            private void genResourceVersion(List<FileInfo> gen_md5_files)
            {
                DirectoryInfo root = new DirectoryInfo(DataDir);
                StringBuilder lines = new StringBuilder();
                {
                    foreach (FileInfo sub in gen_md5_files)
                    {
                        string md5 = CMD5.CalculateMD5(sub);
                        long size = sub.Length;
                        lines.AppendLine(string.Format(string.Format("{0} : {1,12} : {2}", md5, size, sub.FullName.Substring(root.FullName.Length))));
                    }
                    lines.Insert(0, CMD5.CalculateMD5(lines.ToString(), CUtils.UTF8) + "\r\n");
                }
                File.WriteAllText(DataDir + "\\ver.md5", lines.ToString(), CUtils.UTF8);
            }

            /// <summary>
            /// 记录文件更新日期
            /// </summary>
            private static HashMap<string, DateTime> savedPluginFileTimes = new HashMap<string, DateTime>();

            // 检测xls目录下游戏插件是否需要存储//
            private List<FileInfo> checkPlugins()
            {
                List<FileInfo> xls_files = new List<FileInfo>();
                TemplateManager.Factory.Formula.ListXCSVFiles(new DirectoryInfo(DataDir), xls_files);
                //                 foreach (FileInfo sub in CFiles.listAllFiles(xls_dir))
                //                 {
                //                     try
                //                     {
                //                         string ext = sub.Extension.ToLower();
                //                         if (ext.EndsWith(".xls"))
                //                         {
                //                             string fullname = sub.FullName;
                //                             // 检测文件有没有更新
                //                             DateTime lastSaved;
                //                             if (!savedPluginFileTimes.TryGetValue(fullname, out lastSaved) || (lastSaved != sub.LastWriteTime))
                //                             {
                //                                 xls_files.Add(sub);
                //                             }
                //                             Console.WriteLine("Skip Save : " + fullname);
                //                         }
                //                     }
                //                     catch (Exception err)
                //                     {
                //                         MessageBox.Show(err.Message);
                //                     }
                //                 }
                return xls_files;
            }


        }
        //-----------------------------------------------------------------------------------------------------------
        class SerialMaker
        {
            public void Gen(EditorTemplatesData alldata)
            {
                HashMap<uint, ISNData> savedID = new HashMap<uint, ISNData>();
                List<ISNData> datas = new List<ISNData>();
                List<ISNData> regens = new List<ISNData>();
                while (true)
                {
                    savedID.Clear();
                    datas.Clear();
                    regens.Clear();
                    PropertyUtil.CollectFieldTypeValues<ISNData>(alldata, datas);
                    foreach (ISNData sn in datas)
                    {
                        if (savedID.ContainsKey(sn.SerialNumber))
                        {
                            regens.Add(sn);
                        }
                        else
                        {
                            savedID.Put(sn.SerialNumber, sn);
                        }
                    }
                    if (regens.Count > 0)
                    {
                        uint nid = 1;
                        foreach (ISNData sn in regens)
                        {
                            for (; nid < uint.MaxValue; nid++)
                            {
                                if (!savedID.ContainsKey(nid))
                                {
                                    sn.RegenSerialNumber(nid);
                                    break;
                                }
                            }
                        }
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }
        //-----------------------------------------------------------------------------------------------------------
        private class LoadLanguageTask : IProgress
        {
            public override int Value { get { return progress.Value; } }

            private Editor editor;
            private EditorTemplatesData allnodes;
            private AtomicInteger progress = new AtomicInteger(0);
            private CsvTable table = new CsvTable();

            public LoadLanguageTask(string file, Editor editor)
            {
                this.editor = editor;
                this.allnodes = editor.GetEditorTemplatesData();
                this.table.LoadFromText(File.ReadAllText(file, CUtils.UTF8));

                base.Title = "Load Language : " + file;
                base.Text = "替换字段中...";
                base.Maximum = table.MaxRow;
                base.Minimum = 0;
                base.IsDone = false;
            }
            public override void Run()
            {
                EditorTemplates.LoadLocalizationCsv(allnodes, table, progress);
                this.IsDone = true;
            }
            public override void Done()
            {
                editor.RefreshAll();
            }
        }
        //-----------------------------------------------------------------------------------------------------------
        #endregion // _SaveLoad_
        //-----------------------------------------------------------------------------------------------------------

        //------------------------------------------------------------------------------
        #region _Templates_
        //------------------------------------------------------------------------------

        /// <summary>
        /// 获取模板管理器
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public DataManagerPanel<T> GetTemplateManager<T>() where T : class, ITemplateData, new()
        {
            Type type = typeof(T);
            return template_panels[type] as DataManagerPanel<T>;
        }

        /// <summary>
        /// 获取模板管理器根节点
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public TreeNode GetTemplateManagerTreeRoot<T>() where T : class, ITemplateData, new()
        {
            Type type = typeof(T);
            DataManagerPanel<T> panel = template_panels[type] as DataManagerPanel<T>;
            if (panel != null)
            {
                return panel.TreeRoot;
            }
            return null;
        }

        public object GetSelectedObject()
        {
            IDataManager dm = page_panels[tabControl1.SelectedTab];
            if (dm != null)
            {
                return dm.SelectedData;
            }
            return null;
        }

        /// <summary>
        /// 获取模板ID和类型对应的模板对象
        /// </summary>
        /// <param name="id"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public T GetTemplateByType<T>(int id) where T : class, ITemplateData, new()
        {
            Type type = typeof(T);
            DataManagerPanel<T> panel = template_panels[type] as DataManagerPanel<T>;
            if (panel != null)
            {
                return panel.GetNodeData(id.ToString());
            }
            return default(T);
        }
        public object GetTemplateByType(int id, Type type)
        {
            IDataManager panel = template_panels[type] as IDataManager;
            if (panel != null)
            {
                return panel.GetNodeData(id.ToString());
            }
            return null;
        }


        /// <summary>
        /// 获取场景中,玩家出生点对应的UnitTemplateID
        /// </summary>
        /// <param name="mData"></param>
        /// <param name="force"></param>
        /// <returns></returns>
        public static int GetTestActorTemplateID(SceneData mData, int force)
        {
            foreach (RegionData rd in mData.Regions)
            {
                foreach (AbilityData tg in rd.Abilities)
                {
                    if (tg is PlayerStartAbilityData)
                    {
                        PlayerStartAbilityData start = tg as PlayerStartAbilityData;
                        if (start.START_Force == force)
                        {
                            return start.TestActorTemplateID;
                        }
                    }
                }
            }
            return 1;
        }

        /// <summary>
        /// 获取 模板数据 对应的 ID
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="elementType"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool ConvertTemplateID(object obj, out int id)
        {
            if (obj != null)
            {
                if (obj is ITemplateData)
                {
                    id = (obj as ITemplateData).TemplateID;
                    return true;
                }
            }
            id = 0;
            return false;
        }


        /// <summary>
        /// 显示选择Template对象对话框
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="elementType"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        public object ShowSelectTemplateDialog(object obj, Type elementType)
        {
            IDataManager panel = template_panels[elementType] as IDataManager;
            if (panel != null)
            {
                return panel.ShowSelectTemplateDialog(obj);
            }
            return null;
        }


        /// <summary>
        /// 显示选择TemplateID对话框
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="elementType"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool ShowSelectTemplateIDDialog(object obj, Type elementType, out int id)
        {
            IDataManager panel = template_panels[elementType] as IDataManager;
            if (panel != null)
            {
                return panel.ShowSelectTemplateIDDialog(obj, out id);
            }
            id = 0;
            return false;
        }

        /// <summary>
        /// 选择地块
        /// </summary>
        /// <param name="color"></param>
        /// <returns></returns>
        public FormTerrainDefinition ShowTerrainDefinitionDialog(IWin32Window owner, int color = 0)
        {
            var editor = new FormTerrainDefinition();
            editor.SelectedColor = color;
            editor.ShowDialog(owner);
            this.TerrainDefinition = editor.Data;
            saveCFG(this.TerrainDefinition, this.SaveTerrainDefinitionFile);
            return editor;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="owner"></param>
        /// <param name="color"></param>
        /// <returns></returns>
        public FormUnitActionDefinition ShowUnitActionDefinitionDialog(IWin32Window owner)
        {
             var editor = new FormUnitActionDefinition();
             editor.ShowDialog(owner);
             this.UnitActionDefinition = editor.Data;
             saveCFG(this.UnitActionDefinition, this.SaveUnitActionDefinition);
             return editor;
        }

        #endregion

        //-----------------------------------------------------------------------------------------------------------
        #region _Resource_
        //-----------------------------------------------------------------------------------------------------------

        private void InitAllResNode()
        {
            TreeNode root = new TreeNode("资源");
            root.ImageKey = "icons_tool_bar2.png";
            root.SelectedImageKey = "icons_tool_bar2.png";
            InitResNode(root, new DirectoryInfo(Editor.EditorRootDir));
            treeViewRes.Nodes.Clear();
            treeViewRes.Nodes.Add(root);
            treeViewRes.CollapseAll();
        }

        private int InitResNode(TreeNode parent, DirectoryInfo dir)
        {
            int count = 0;
            foreach (FileInfo f in dir.GetFiles())
            {
                if (EditorPlugin.CurrentPlugin.AcceptResource(EditorPlugin.DefaultPlugin, f.Name))
                {
                    TreeNode sub = new TreeNode(f.Name);
                    sub.Tag = f;
                    sub.ImageKey = "icon_res.png";
                    sub.SelectedImageKey = "icon_res.png";
                    parent.Nodes.Add(sub);
                    count++;
                }
            }
            foreach (DirectoryInfo d in dir.GetDirectories())
            {
                TreeNode sub = new TreeNode(d.Name);
                int scount = InitResNode(sub, d);
                if (scount > 0)
                {
                    sub.Tag = d;
                    sub.ImageKey = "icons_tool_bar2.png";
                    sub.SelectedImageKey = "icons_tool_bar2.png";
                    parent.Nodes.Add(sub);
                }
                count += scount;
            }
            return count;
        }

        private void treeViewRes_ItemDrag(object sender, ItemDragEventArgs e)
        {
            treeViewRes.DoDragDrop(e.Item, DragDropEffects.Move);
        }
        private void listView1_DragDrop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(typeof(TreeNode)))
            {
                TreeNode node = e.Data.GetData(typeof(TreeNode)) as TreeNode;
                if (node.Tag is FileInfo)
                {
                    FileInfo fi = node.Tag as FileInfo;
                    ListViewItem item = new ListViewItem(fi.Name);
                    item.ImageKey = "icon_res.png";
                    item.Tag = fi;
                    listViewRes.Items.Add(item);
                }
            }
        }
        private void listView1_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(typeof(TreeNode)))
            {
                TreeNode node = e.Data.GetData(typeof(TreeNode)) as TreeNode;
                if (node.Tag is FileInfo)
                {
                    e.Effect = DragDropEffects.Move;
                    return;
                }
            }
            e.Effect = DragDropEffects.None;
        }
        private void listView1_DragOver(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(typeof(TreeNode)))
            {
                TreeNode node = e.Data.GetData(typeof(TreeNode)) as TreeNode;
                if (node.Tag is FileInfo)
                {
                    e.Effect = DragDropEffects.Move;
                    return;
                }
            }
            e.Effect = DragDropEffects.None;
        }

        private void treeViewRes_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if (e.Node.Tag is FileInfo)
            {
                try
                {
                    FileInfo ff = e.Node.Tag as FileInfo;
                    EditorPlugin.CurrentPlugin.RunModelView(EditorPlugin.DefaultPlugin, new string[] { ff.FullName });
                }
                catch (Exception err)
                {
                    MessageBox.Show(err.Message);
                }
            }
        }

        private void btnRunRes_Click(object sender, EventArgs e)
        {
            List<string> ffs = new List<string>();
            foreach (ListViewItem item in listViewRes.Items)
            {
                if (item.Tag is FileInfo)
                {
                    FileInfo ffi = item.Tag as FileInfo;
                    ffs.Add(ffi.FullName);
                }
            }
            try
            {
                EditorPlugin.CurrentPlugin.RunModelView(EditorPlugin.DefaultPlugin, ffs.ToArray());
            }
            catch (Exception err)
            {
                MessageBox.Show(err.Message);
            }
        }

        private void btnRemoveRes_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem item in listViewRes.SelectedItems)
            {
                listViewRes.Items.Remove(item);
            }
        }

        private void btnRefreshRes_Click(object sender, EventArgs e)
        {
            listViewRes.Items.Clear();
        }

        private void btn_CleanRes_Click(object sender, EventArgs e)
        {
            new G2DProgressDialog(new CleanResTask(this)).ShowDialog(this);
        }
        private void btn_OutputRes_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog dialog = new FolderBrowserDialog();
            dialog.SelectedPath = DataDir;
            if (dialog.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
            {
                if (!dialog.SelectedPath.Equals(DataDir))
                {
                    new G2DProgressDialog(new CleanResTask(this, dialog.SelectedPath)).ShowDialog(this);
                }
            }
        }

        public class CleanResTask : IProgress
        {
            private readonly Editor editor;
            private EditorTemplates templates;
            private EditorTemplatesData datas;
            private List<int> scenes_list;

            private AtomicInteger used_progress = new AtomicInteger(0);
            private SortedDictionary<string, AtomicInteger> file_list = new SortedDictionary<string, AtomicInteger>();
            private int used_count = 0;
            private int unused_count = 0;
            private int miss_count = 0;
            private StringBuilder logs = new StringBuilder();

            private AtomicInteger copy_progress = new AtomicInteger(0);
            private List<FileInfo> copyres = new List<FileInfo>();
            private HashSet<string> ignores = new HashSet<string>();
            private DirectoryInfo output_dir;

            public override int Value
            {
                get
                {
                    return used_progress.Value + copy_progress.Value;
                }
            }

            public CleanResTask(Editor editor, string outputDir = null)
            {
                this.editor = editor;
                this.templates = new EditorTemplates(DataDir, TemplateManager.MessageCodec);
                this.templates.LoadAllTemplates();
                this.datas = templates.AllTemplatesExcludeScenes;
                this.scenes_list = templates.ListScenes();


                List<FileInfo> allfiles = CFiles.listAllFiles(new DirectoryInfo(ResDir));
                foreach (FileInfo file in allfiles)
                {
                    file_list.Add(file.FullName, new AtomicInteger(0));
                }

                if (outputDir != null)
                {
                    output_dir = new DirectoryInfo(outputDir);
                    CFiles.listAllFiles(copyres, new DirectoryInfo(DataDir));
                    CFiles.listAllFiles(copyres, new DirectoryInfo(ResDir));
                }

                base.Maximum = datas.FileCount + scenes_list.Count + copyres.Count;
                base.Minimum = 0;
                base.Value = 0;
                base.Title = "检测资源文件使用";
            }

            public override void Run()
            {
                logs.AppendLine("------------------------------------------------------------------");
                logs.AppendLine("- 缺失文件统计 -");
                logs.AppendLine("------------------------------------------------------------------");
                //检测所有模板资源使用率//
                foreach (ITemplateData data in datas.AllTemplates())
                {
                    base.Text = string.Format("{0}/{1} : {2}", Value, Maximum, data);
                    try
                    {
                        MarkInResources(data);
                    }
                    catch (Exception err)
                    {
                        logs.AppendLine(err.Message);
                    }
                    finally { this.used_progress.IncrementAndGet(); }
                }
                //检测所有场景资源使用率//
                foreach (int scene_id in scenes_list)
                {
                    try
                    {
                        SceneData sdata = templates.LoadScene(scene_id);
                        if (sdata != null)
                        {
                            base.Text = string.Format("{0}/{1} : scene : {2}", Value, Maximum, sdata);
                            MarkInResources(sdata);
                        }
                    }
                    catch (Exception err)
                    {
                        logs.AppendLine(err.Message);
                    }
                    finally { this.used_progress.IncrementAndGet(); }
                }
                logs.AppendLine("------------------------------------------------------------------");
                logs.AppendLine("- 已使用文件统计 -");
                logs.AppendLine("------------------------------------------------------------------");
                //生成报表//
                foreach (KeyValuePair<string, AtomicInteger> used in file_list)
                {
                    string res = used.Key.Substring(EditorRootDir.Length);
                    int count = used.Value.Value;
                    if (count > 0)
                    {
                        used_count++;
                        logs.AppendLine(string.Format("已使用文件:,{0} ,次数:{1}", res, count));
                    }
                }
                logs.AppendLine("------------------------------------------------------------------");
                logs.AppendLine("- 未使用文件统计 -");
                logs.AppendLine("------------------------------------------------------------------");
                foreach (KeyValuePair<string, AtomicInteger> used in file_list)
                {
                    string res = used.Key.Substring(EditorRootDir.Length);
                    int count = used.Value.Value;
                    if (count <= 0)
                    {
                        ignores.Add(used.Key);
                        unused_count++;
                        logs.AppendLine(string.Format("未使用文件:,{0}", res));
                    }
                }
                logs.AppendLine("------------------------------------------------------------------");

                File.WriteAllText(EditorRootDir + "\\resource_info.csv", logs.ToString(), CUtils.UTF8);
                //复制资源//
                if (output_dir != null && output_dir.Exists)
                {
                    CFiles.DirectoryCopy(DataDir, output_dir.FullName + "\\data", true, CopyResFilter, copy_progress);
                    CFiles.DirectoryCopy(ResDir, output_dir.FullName + "\\res", true, CopyResFilter, copy_progress);
                }
            }

            private void CopyResFilter(FileInfo src, out bool ignore)
            {
                ignore = ignores.Contains(src.FullName);
                if (!ignore)
                {
                    base.Text = string.Format("复制资源 : " + src);
                }
            }

            public override void Done()
            {
                MessageBox.Show(
                    "资源检测结束!" +
                    "\n * 已使用文件:" + used_count +
                    "\n * 未使用文件:" + unused_count +
                    "\n * 缺失文件数:" + miss_count +
                    "\n报告已存入:" + EditorRootDir + "\\resource_info.csv"
                    );
            }

            private void MarkInResources(object data)
            {
                HashMap<string, FieldAttributeValue> reses = templates.SelectTemplatesAsMap(data);

                foreach (KeyValuePair<string, FieldAttributeValue> res in reses)
                {
                    if (!string.IsNullOrWhiteSpace(res.Key))
                    {
                        FileInfo file = new FileInfo((Editor.EditorRootDir + "\\" + res.Key).Trim());
                        AtomicInteger usecount;
                        if (file_list.TryGetValue(file.FullName, out usecount))
                        {
                            usecount.IncrementAndGet();
                        }
                        else
                        {
                            miss_count++;
                            logs.AppendLine(string.Format("缺失文件:,{0} ,对象:{1}, 类型:{2},字段:{3}", res.Key, data, data.GetType(), res.Value.Field.Name));
                        }
                    }
                }
            }
        }

        #endregion

        //------------------------------------------------------------------------------
        #region _Editor_Delegate_And_Events_
        //------------------------------------------------------------------------------

        private void Editor_Load(object sender, EventArgs e)
        {
            try
            {
                this.Text = "GameEditor : " + EditorRootDir;

                loadCFG();
                InitAllResNode();
                InitAllTempaltes();
                if (autoSave)
                {
                    saveAll();
                    SaveEditorStatus();
                    Dispose(true);
                }
                    
               // CommonSecure.ConnectWS.Run(this);
            }
            catch (Exception err)
            {
                MessageBox.Show(err.Message);
            }
        }

        private void Editor_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (MessageBox.Show(this,
                "确认关闭?",
                "确认关闭?",
                MessageBoxButtons.OKCancel) == System.Windows.Forms.DialogResult.OK)
            {
                this.SaveEditorStatus();
            }
            else
            {
                e.Cancel = true;
            }
        }

        private void btn_saveAll_Click(object sender, EventArgs e)
        {
            saveAll();
        }
        private void btn_saveALLCheck_Click(object sender, EventArgs e)
        {
            saveAll(true);
        }

        private void sceneBtn_DoubleClickNode(object sender, TreeNodeMouseClickEventArgs e)
        {
            OpenScene(scenes.GetSelectedNode(), new Win32ScenePlugin());
        }
        private void sceneBtn_OpenNodeWin32_Click(object sender, EventArgs e)
        {
            OpenScene(scenes.GetSelectedNode(), new Win32ScenePlugin());
        }
        private void sceneBtn_OpenNode_Click(object sender, EventArgs e)
        {
            OpenScene(scenes.GetSelectedNode(), EditorPlugin.CurrentPlugin.CreateScenePlugin(EditorPlugin.DefaultPlugin));
        }
        private void sceneBtn_TestAstar_Click(object sender, EventArgs e)
        {
            var sd = scenes.GetSelectedData();
            if (sd != null)
            {
                new GameEditorPlugin.Tools.FormAstar(DataDir_scenes, Editor.Instance.TerrainDefinition, sd).Show();
            }
        }

        private void btn_CopyText_Click(object sender, EventArgs e)
        {

            object node = GetSelectedObject();
            if (node is ITemplateData)
            {
                Clipboard.SetText((node as ITemplateData).TemplateID.ToString());
            }
        }

        private void sceneBtn_RunEMU_Click(object sender, EventArgs e)
        {
            SceneData data = scenes.GetSelectedData();
            if (data != null)
            {
                IGameEditorPlugin plugin = EditorPlugin.CurrentPlugin;
                plugin.RunLocalPlay(EditorPlugin.DefaultPlugin, new DirectoryInfo(DataDir), data.ID, false);
            }
        }
        private void sceneBtn_RunEMUServer_Click(object sender, EventArgs e)
        {
            SceneData data = scenes.GetSelectedData();
            if (data != null)
            {
                IGameEditorPlugin plugin = EditorPlugin.CurrentPlugin;
                plugin.RunServerPlay(EditorPlugin.DefaultPlugin, new DirectoryInfo(DataDir), data.ID);
            }
        }
        private void sceneBtn_RunREC_Click(object sender, EventArgs e)
        {
            SceneData data = scenes.GetSelectedData();
            if (data != null)
            {
                IGameEditorPlugin plugin = EditorPlugin.CurrentPlugin;
                plugin.RunLocalPlay(EditorPlugin.DefaultPlugin, new DirectoryInfo(DataDir), data.ID, true);
            }
        }

        private void sceneBtn_LoadREC_Click(object sender, EventArgs e)
        {
            LoadBattleRecord();
        }

        private void sceneBtn_RunGAME_Click(object sender, EventArgs e)
        {
            SceneData data = scenes.GetSelectedData();
            if (data != null)
            {
                try
                {
                    IGameEditorPlugin plugin = EditorPlugin.CurrentPlugin;
                    plugin.RunTest(EditorPlugin.DefaultPlugin, DataDir, data.ID, GetTestActorTemplateID(data, 0));
                }
                catch (Exception err)
                {
                    MessageBox.Show(err.Message);
                }
            }
        }
        private void btn_SetTemplateConfig_Click(object sender, EventArgs e)
        {
            G2DFieldEditor editor = new G2DFieldEditor(this.CFG.GetType(), this.CFG, false);
            if (editor.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
            {
                if (editor.EditObject != null)
                {
                    this.CFG = (Config)editor.EditObject;
                    saveCFG(this.CFG, this.SaveCfgFile);
                }
            }
        }
        private void btn_DefineTerrain_Click(object sender, EventArgs e)
        {
            ShowTerrainDefinitionDialog(this);
        }
        private void btn_DefineUnitAction_Click(object sender, EventArgs e)
        {
            ShowUnitActionDefinitionDialog(this);
        }
        private void btn_SetTemplateExtConfig_Click(object sender, EventArgs e)
        {
            G2DFieldEditor editor = new G2DFieldEditor(this.ExtCFG.GetType(), this.ExtCFG, false);
            if (editor.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
            {
                if (editor.EditObject != null)
                {
                    this.ExtCFG = (ICommonConfig)editor.EditObject;
                    saveCFG(this.ExtCFG, this.SaveCfgExtFile);
                }
            }
        }


        private void btn_ScriptEdit_Click(object sender, EventArgs e)
        {

        }

        private void btn_LoadLanguageCsv_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.InitialDirectory = EditorRootDir;
            ofd.Filter = "CSV语言配置(*.csv)|*.csv|文本文件(*.txt)|*.txt|所有文件(*.*)|*.*";
            if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                try
                {
                    LoadLanguageTask task = new LoadLanguageTask(ofd.FileName, this);
                    new G2DProgressDialog(task).ShowDialog(this);
                }
                catch (Exception err)
                {
                    MessageBox.Show(err.Message);
                }
            }
        }
        private void btn_PlayBattleRecord_Click(object sender, EventArgs e)
        {
            LoadBattleRecord();
        }
        private void openUnitEvent_Click(object sender, EventArgs e)
        {
            UnitEventTemplate temp = unit_events.GetSelectedData();
            if (temp != null)
            {
                CommonAIEditor.Unit.UnitEventEditor eventEditor = new CommonAIEditor.Unit.UnitEventEditor(unit_events, temp);
                eventEditor.FormClosed += new FormClosedEventHandler(
                    (object sender2, FormClosedEventArgs e2) =>
                    {
                        eventEditor.Save();
                        eventEditor = null;
                    }
                );
                eventEditor.Show();
            }
        }


        //-----------------------------------------------------------------------------------------------------------
        #endregion // Events //

        //-----------------------------------------------------------------------------------------------------------
        private void OpenScene(G2DTreeNode<SceneData> node, ISceneEditorPlugin plugin = null)
        {
            if (plugin == null)
            {
                plugin = EditorPlugin.CurrentPlugin.CreateScenePlugin(EditorPlugin.DefaultPlugin);
            }
            if (node != null)
            {
                SceneEditor editor = new SceneEditor(scenes, node, plugin);
                editor.OnSaved += this.sceneEditor_onSavedScene;
                editor.Show();
            }
        }

        private void LoadBattleRecord()
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.InitialDirectory = EditorRootDir;
            ofd.Filter = "REC战报文件(*.rec)|*.rec|所有文件(*.*)|*.*";
            if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                try
                {
                    FileStream fis = new FileStream(ofd.FileName, FileMode.Open, FileAccess.Read);
                    FormRuntimeGameReplay view = new FormRuntimeGameReplay();
                    view.StartPlay(DataDir, fis);
                    view.Show();
                }
                catch (Exception err)
                {
                    MessageBox.Show(err.Message);
                }
            }
        }

    }
}