using CommonAI.RTS;
using CommonAI.Zone;
using CommonAI.Zone.Instance;
using CommonAI.Zone.ZoneEditor;
using CommonAIClient.Client;
using CommonFroms;
using CommonFroms.G2D;
using CommonFroms.Utils;
using CommonLang;
using CommonLang.Concurrent;
using CommonLang.Vector;
using GameEditorPlugin;
using GameEditorPlugin.Win32.BattleClient;
using GameEditorPlugin.Win32.Runtime;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using XmdsServerNode.Node;
using XmdsServerTest.Server;
using XmdsServerTestBots.Bot;

namespace XmdsServerTest
{
    public partial class FormTest : Form
    {
        private NodeTestServer server;
        private Random random = new Random();
        private List<UnitInfo> bot_templates = new List<UnitInfo>();
        private AtomicInteger bot_indexer = new AtomicInteger(1);

        public FormTest(NodeTestServer server)
        {
            InitializeComponent();
            this.pictureBoxRoomLayer.MouseWheel += new MouseEventHandler(pictureBoxRoomLayer_MouseWheel);

            this.listView_Nodes.ContextMenuStrip = menu_Node;
            this.server = server;
            this.bot_templates.AddRange(server.ListTestPlayerTemplates());
        }

        private void FormTest_FormClosing(object sender, FormClosingEventArgs e)
        {
            this.server.Shutdown();
        }
        private void timer1_Tick(object sender, EventArgs e)
        {
            if (server.Running)
            {
                RefreshZoneNodes();
            }
        }
        private void timer2_Tick(object sender, EventArgs e)
        {
            if (server.Running)
            {
                UpdateZoneNodes();
                pictureBoxRoomLayer.Refresh();
            }
        }

        private void timer3_Tick(object sender, EventArgs e)
        {
            if (server.Running)
            {
                ServerZoneNode node = SelectedZoneNode();
                if (node != null)
                {
                    this.RemoveAllPlayer(node);

                    UnitInfo unit1 = ZoneNodeManager.Templates.Templates.getUnit(100861);
                    UnitInfo unit2 = ZoneNodeManager.Templates.Templates.getUnit(100862);
                    UnitInfo unit3 = ZoneNodeManager.Templates.Templates.getUnit(100863);
                    UnitInfo unit4 = ZoneNodeManager.Templates.Templates.getUnit(100864);
                    UnitInfo unit5 = ZoneNodeManager.Templates.Templates.getUnit(100865);
                    this.AddBots(node, unit1, 10, 20);
                    this.AddBots(node, unit2, 11, 20);
                    this.AddBots(node, unit3, 12, 20);
                    this.AddBots(node, unit4, 13, 20);
                    this.AddBots(node, unit5, 14, 20);
                }
            }
        }


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

        #region _ZoneNodes列表刷新以及显示_
        private class ListViewTagComparer : System.Collections.IComparer
        {
            public int Compare(object x, object y)
            {
                ServerZoneNode stag = x as ServerZoneNode;
                BattleView dtag = y as BattleView;
                return (dtag.Node == stag) ? 0 : -1;
            }
        }
        private void RefreshZoneNodes()
        {
            this.lbl_Status.Text = server.Status;
            if (server.Running)
            {
                IList<ServerZoneNode> nodes = server.ListZoneNodes();
                if (!FormUtils.ListViewItemTagEquals(listView_Nodes, (System.Collections.IList)nodes, new ListViewTagComparer()))
                {
                    listView_Nodes.SuspendLayout();
                    listView_Nodes.Items.Clear();
                    foreach (ServerZoneNode node in nodes)
                    {
                        ListViewItem nodeItem = new ListViewItem(node.UUID.ToString());
                        nodeItem.SubItems.Add(node.ToString());
                        nodeItem.SubItems.Add(node.PlayerCount.ToString());
                        nodeItem.Tag = new BattleView(node);
                        listView_Nodes.Items.Add(nodeItem);
                    }
                    listView_Nodes.ResumeLayout();
                }
                else
                {
                    foreach (ListViewItem nodeItem in listView_Nodes.Items)
                    {
                        ServerZoneNode node = (nodeItem.Tag as BattleView).Node;
                        nodeItem.SubItems[1].Text = (node.ToString());
                        nodeItem.SubItems[2].Text = (node.PlayerCount.ToString());
                    }
                }
            }
            else
            {
                listView_Nodes.Items.Clear();
            }
        }
        private void UpdateZoneNodes()
        {
            this.lbl_Status.Text = server.Status;
            if (server.Running)
            {
                foreach (ListViewItem nodeItem in listView_Nodes.Items)
                {
                    BattleView view = (nodeItem.Tag as BattleView);
                    view.update();
                }
            }
        }
        public ServerZoneNode SelectedZoneNode()
        {
            if (listView_Nodes.SelectedItems.Count > 0)
            {
                return (listView_Nodes.SelectedItems[0].Tag as BattleView).Node;
            }
            return null;
        }
        public BattleView SelectedBattleView()
        {
            if (listView_Nodes.SelectedItems.Count > 0)
            {
                return listView_Nodes.SelectedItems[0].Tag as BattleView;
            }
            return null;
        }

        //----------------------------------------------------------------------------------------------------------------------
        private void listView_Nodes_SelectedIndexChanged(object sender, EventArgs e)
        {

            BattleView bv = SelectedBattleView();
            if (bv != null)
            {
                float scale = Math.Max(
                    ((float)pictureBoxRoomLayer.Width) / bv.Width,
                    ((float)pictureBoxRoomLayer.Height) / bv.Height);
                bv.setCamera(bv.Width / 2, bv.Height / 2);
                bv.setCameraScale(scale, scale);
            }

        }

        #endregion

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

        #region __BattleView__


        public class BattleLocalView : BattleLocal
        {
            private EditorScene mZone;
            public BattleLocalView(EditorScene zone)
                : base(ZoneNodeManager.Templates)
            {
                this.mZone = zone;
                this.Layer.ProcessMessage(new CommonAI.ZoneClient.ClientEnterScene(mZone.Data.ID, mZone.SpaceDivSize, ZoneNodeManager.Templates.Templates.ResourceVersion));
            }
            public override EditorScene Zone
            {
                get { return mZone; }
            }
        }
        public class BattleView : DisplayBattleLocal<BattleLocalView>
        {
            public ServerZoneNode Node { get { return room; } }
            private ServerZoneNode room;
            private long mLastUpdateTime;
            public BattleView(ServerZoneNode room)
            {
                base.ShowGuardRange = false;
                base.ShowAttackRange = false;
                base.ShowDamageRange = false;
                base.ShowName = true;
                base.ShowHP = true;
                this.room = room;
                base.InitClient(new BattleLocalView(room.Zone));
                this.room.Zone.OnPostEvent += zone_OnPostEvent;
                this.room.Zone.OnUpdate += zone_OnUpdate;
            }
            private void zone_OnPostEvent(InstanceZone zone, Event e)
            {
                Battle.onEventHandler(e);
            }
            private void zone_OnUpdate(CommonAI.Zone.Instance.InstanceZone zone)
            {
                SyncPosEvent.UnitPos pos = new SyncPosEvent.UnitPos();
                foreach (CommonAI.Zone.Instance.InstanceZoneObject so in room.Zone.AllObjects)
                {
                    CommonAI.ZoneClient.ZoneObject co = Client.Layer.GetObject(so.ID);
                    if (co != null)
                    {
                        pos = so.GetSyncPos();
                        co.SyncPos(ref pos);
                    }
                }
            }
            protected override void clientUpdate(int intervalMS)
            {
                Battle.BeginUpdate(intervalMS);
                Battle.Update();
            }
            public void update()
            {
                long curTime = CommonLang.CUtils.CurrentTimeMS;
                if (mLastUpdateTime == 0)
                {
                    mLastUpdateTime = curTime;
                }
                int intervalMS = (int)(curTime - mLastUpdateTime);
                this.mLastUpdateTime = curTime;
                base.update(intervalMS);
            }

        }

        private Vector2 pic_lastMouesDown;
        private Vector2 pic_lastCameraPos;

        private void pictureBoxRoomLayer_MouseWheel(object sender, MouseEventArgs e)
        {
            try
            {
                BattleView bv = SelectedBattleView();
                if (bv != null)
                {
                    int d = CMath.getDirect(e.Delta);
                    if (d > 0)
                    {
                        float newD = bv.getCameraScale() * 1.1f;
                        bv.setCameraScale(newD, newD);
                    }
                    else if (d < 0)
                    {
                        float newD = bv.getCameraScale() / 1.1f;
                        bv.setCameraScale(newD, newD);
                    }
                }
            }
            catch (Exception err)
            {
                Console.WriteLine(err.Message);
            }
        }
        private void pictureBoxRoomLayer_MouseDown(object sender, MouseEventArgs e)
        {
            pictureBoxRoomLayer.Focus();
            BattleView bv = SelectedBattleView();
            if (bv != null)
            {
                if (e.Button == System.Windows.Forms.MouseButtons.Right)
                {
                    pic_lastMouesDown = new Vector2(e.Location.X, e.Location.Y);
                    pic_lastCameraPos = new Vector2(bv.CameraX, bv.CameraY);
                }
            }
        }
        private void pictureBoxRoomLayer_MouseUp(object sender, MouseEventArgs e)
        {
            pic_lastMouesDown = null;
            pic_lastCameraPos = null;
        }

        private void pictureBoxRoomLayer_MouseMove(object sender, MouseEventArgs e)
        {
            BattleView bv = SelectedBattleView();
            if (bv != null)
            {
                if (e.Button == System.Windows.Forms.MouseButtons.Right)
                {
                    if (pic_lastMouesDown != null)
                    {
                        float x = pic_lastCameraPos.X + bv.screenToWorldSizeX(pic_lastMouesDown.X - e.X);
                        float y = pic_lastCameraPos.Y + bv.screenToWorldSizeY(pic_lastMouesDown.Y - e.Y);
                        bv.setCamera(x, y);
                    }
                }
            }
        }
        private void pictureBoxRoomLayer_Paint(object sender, PaintEventArgs e)
        {
            try
            {
                BattleView bv = SelectedBattleView();
                if (bv != null)
                {
                    bv.setWindow(new RectangleF(0, 0, pictureBoxRoomLayer.Width, pictureBoxRoomLayer.Height));
                    bv.render(e.Graphics);
                }
            }
            catch (Exception err)
            {
                Console.WriteLine(err.Message);
            }
        }

        #endregion

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

        #region __测试客户端__

        private void btn_AddScene_Click(object sender, EventArgs e)
        {
            var list = ZoneNodeManager.Templates.LoadAllScenes();
            var dialog = new G2DListSelectEditor<SceneData>(list);
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                var temp = dialog.SelectedObject;
                if (temp != null)
                {
                    try
                    {
                        var node = NodeTestServer.Instance.AddTestScene(temp.ID);
                    }
                    catch (Exception err)
                    {
                        MessageBox.Show(err.Message);
                    }
                }
            }
        }
        private void btn_AddAllScene_Click(object sender, EventArgs e)
        {
            foreach (var sceneID in ZoneNodeManager.Templates.ListScenes())
            {
                try
                {
                    var node = NodeTestServer.Instance.AddTestScene(sceneID);
                }
                catch (Exception err)
                {
                    MessageBox.Show(err.Message);
                }
            }
        }
        private void btn_AddBatchBots_Click(object sender, EventArgs e)
        {
            string _count = G2DTextDialog.Show(server.ZoneNodesCount.ToString(), "输入数量");
            int count;
            if (_count != null && int.TryParse(_count, out count))
            {
                AddBots(count);
            }
        }

        private void menuBtn_AddPlayer_Click(object sender, EventArgs e)
        {
            ServerZoneNode node = SelectedZoneNode();
            if (node != null)
            {
                AddTestClient(node);
            }
        }

        private void addBatchBotsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string _count = G2DTextDialog.Show(server.ZoneNodesCount.ToString(), "输入数量");
            int count;
            if (_count != null && int.TryParse(_count, out count))
            {
                ServerZoneNode node = SelectedZoneNode();
                if (node != null)
                {
                    AddBots(node, count);
                }
            }
        }

        private void removeAllPlayerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ServerZoneNode node = SelectedZoneNode();
            if (node != null)
            {
                RemoveAllPlayer(node);
            }
        }

        //-------------------------------------------------------------------------------------------------------------------------
        #region PlayerAPI

        private void AddTestClient(ServerZoneNode node)
        {
            string tempID = G2DTextDialog.Show(3.ToString(), "输入单位模板ID");
            int unit_template_id;
            if (tempID != null && int.TryParse(tempID, out unit_template_id))
            {
                try
                {
                    var client = FormTestClient.StartWinForm(unit_template_id, 2, node.UUID, node.SceneID);
                }
                catch (Exception err)
                {
                    MessageBox.Show(err.Message);
                }
            }
        }
        public void AddBot()
        {
            UnitInfo unit = CUtils.GetRandomInArray<UnitInfo>(bot_templates, random);
            if (unit != null)
            {
                string name = unit.Name + "_" + bot_indexer.IncrementAndGet();
                BotPlayer ret = new BotPlayer(name, "", unit, 0,
                    ZoneNodeManager.Templates,
                    NodeTestServer.Instance.ClientConnectString);
                ret.Start();
            }
        }
        public void AddBots(int count)
        {
            for (int i = 0; i < count; i++)
            {
                AddBot();
            }
        }
        public void AddBot(ServerZoneNode node)
        {
            string tempID = G2DTextDialog.Show(3.ToString(), "输入单位模板ID");
            int unit_template_id;
            if (tempID != null && int.TryParse(tempID, out unit_template_id))
            {
                UnitInfo unit = ZoneNodeManager.Templates.Templates.getUnit(unit_template_id);
                if (unit != null)
                {
                    string name = unit.Name + "_" + bot_indexer.IncrementAndGet();
                    BotPlayer ret = new BotPlayer(name, "", unit, 0,
                        ZoneNodeManager.Templates,
                        NodeTestServer.Instance.ClientConnectString);
                    ret.Start();
                }
            }
        }
        public void AddBots(ServerZoneNode node, int count)
        {
            string tempID = G2DTextDialog.Show(3.ToString(), "输入单位模板ID");
            int unit_template_id;
            if (tempID != null && int.TryParse(tempID, out unit_template_id))
            {
                UnitInfo unit = ZoneNodeManager.Templates.Templates.getUnit(unit_template_id);
                if (unit != null)
                {
                    for (int i = 0; i < count; i++)
                    {
                        string name = unit.Name + "_" + bot_indexer.IncrementAndGet();
                        BotPlayer ret = new BotPlayer(name, "", unit, 0,
                            ZoneNodeManager.Templates,
                            NodeTestServer.Instance.ClientConnectString);
                        ret.Start();
                    }
                }
            }
        }
        public void AddBots(ServerZoneNode node, UnitInfo unit, int force, int count)
        {
            for (int i = 0; i < count; i++)
            {
                string name = unit.Name + "_" + bot_indexer.IncrementAndGet();
                BotPlayer ret = new BotPlayer(name, "", unit, force,
                    ZoneNodeManager.Templates,
                    NodeTestServer.Instance.ClientConnectString);
                ret.Start();
            }
        }

        private void RemoveAllPlayer(ServerZoneNode node)
        {
            using (var plist = ListObjectPool<ServerZoneNode.PlayerClient>.AllocAutoRelease())
            {
                node.ForEachPlayers((p) => { plist.Add(p); });
                foreach (var p in plist)
                {
                    var pc = (p.Client as ServerZoneNode.ZoneNodePlayer).SessionPlayer as AppSessionPlayer;
                    pc.ForceExit();
                }
            }
        }


        #endregion

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


        #endregion

        private void gCToolStripMenuItem_Click(object sender, EventArgs e)
        {
            GC.Collect();
            GC.WaitForFullGCComplete();
        }

        //----------------------------------------------------------------------------------------------------------------------
    }
}