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 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 ZeusServerNode.Node;

namespace ZeusServerTest
{
    public partial class FormTest : Form
    {
        private NodeTestServer server;
        private NodeTestClientGroup bots = new NodeTestClientGroup();
        private Random random = new Random(); 

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

            this.listView_Nodes.ContextMenuStrip = menu_Node;
            this.server = new NodeTestServer(new DirectoryInfo(Application.StartupPath));
        }

        private void FormTest_Load(object sender, EventArgs e)
        {
            new Thread(server.Start).Start();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (server.Running)
            {
                RefreshZoneNodes();
            }
        }
        private void timer2_Tick(object sender, EventArgs e)
        {
            if (server.Running)
            {
                UpdateZoneNodes();
                bots.Update();
                pictureBoxRoomLayer.Refresh();
            }
        }

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

        #region _ZoneNodes列表刷新以及显示_
        private class ListViewTagComparer : System.Collections.IComparer
        {
            public int Compare(object x, object y)
            {
                ZoneNode stag = x as ZoneNode;
                BattleView dtag = y as BattleView;
                return (dtag.Node == stag) ? 0 : -1;
            }
        }
        private void RefreshZoneNodes()
        {
            this.lbl_Status.Text = server.Status;
            if (server.Running)
            {
                IList<ZoneNode> nodes = server.ListZoneNodes();
                if (!FormUtils.ListViewItemTagEquals(listView_Nodes, (System.Collections.IList)nodes, new ListViewTagComparer()))
                {
                    listView_Nodes.SuspendLayout();
                    listView_Nodes.Items.Clear();
                    foreach (ZoneNode node in nodes)
                    {
                        ListViewItem nodeItem = new ListViewItem(node.SceneID.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)
                    {
                        ZoneNode 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 ZoneNode 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.SpaceDIV, ZoneNodeManager.Templates.Templates.ResourceVersion));
            }
            public override EditorScene Zone
            {
                get { return mZone; }
            }
        }
        public class BattleView : DisplayBattleLocal<BattleLocalView>
        {
            public ZoneNode Node { get { return room; } }
            private ZoneNode room;
            private long mLastUpdateTime;
            public BattleView(ZoneNode room)
            {
                base.ShowGuardRange = false;
                base.ShowAttackRange = false;
                base.ShowDamageRange = false;
                base.ShowName = true;
                base.ShowHP = true;
                base.ShowGrid = 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.allObjs())
                {
                    CommonAI.ZoneClient.ZoneObject co = Client.Layer.GetObject(so.ID);
                    if (co != null)
                    {
                        pos.ID = so.ID;
                        pos.X = so.X;
                        pos.Y = so.Y;
                        pos.Z = so.Z;
                        pos.Direction = so.Direction;
                        if (so is CommonAI.Zone.Instance.InstanceUnit)
                        {
                            CommonAI.Zone.Instance.InstanceUnit su = so as CommonAI.Zone.Instance.InstanceUnit;
                            pos.ST = (byte)su.CurrentActionStatus;
                        }
                        else
                        {
                            pos.ST = 0;
                        }
                        co.SyncPos(pos);
                    }
                }
            }
            protected override void clientUpdate(int intervalMS)
            {
                Battle.BeginUpdate(intervalMS);
                Battle.Update(intervalMS);
            }
            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 menuBtn_AddPlayer_Click(object sender, EventArgs e)
        {
            ZoneNode node = SelectedZoneNode();
            if (node != null)
            {
                AddTestClient(node);
            }
        }
        private void menuBtn_AddBots_Click(object sender, EventArgs e)
        {
            ZoneNode node = SelectedZoneNode();
            if (node != null)
            {
                AddTestClientGroup(node);
            }
        }


        private void AddTestClient(ZoneNode node)
        {
            string tempID = G2DTextDialog.Show(21.ToString(), "输入单位模板ID");
            int unit_template_id;
            if (tempID != null && int.TryParse(tempID, out unit_template_id))
            {
                try
                {
                    NodeTestBattleClient client = server.GenBattleClient(node, unit_template_id);
                    new FormTestClient(client).Show();
                }
                catch (Exception err)
                {
                    MessageBox.Show(err.Message);
                }
            }
        }
        private void AddTestClientGroup(ZoneNode node)
        {
            string count = G2DTextDialog.Show(10.ToString(), "添加单位数量");
            int bot_count;
            if (count != null && int.TryParse(count, out bot_count))
            {
                try
                {
                    for (int i = 0; i < bot_count; i++)
                    {
                        UnitInfo temp = CUtils.GetRandomInArray<UnitInfo>(server.PlayerTemplates, random);
                        NodeTestBattleClient client = server.GenBattleClient(node, temp.ID);
                        bots.AddClient(client);
                    }
                }
                catch (Exception err)
                {
                    MessageBox.Show(err.Message);
                }
            }
        }


        #endregion

    }
}