using CommonAI.ZoneClient;
using CommonLang;
using CommonLang.Log;
using pomelo.area;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using XmdsBattleClient.Client;
using XmdsBattleClientBot.XmdsBot;
using XmdsCommonServer.Message;

namespace XmdsBattleClientBot.Bot
{
    /// <summary>
    /// 全自动战斗机器人,基础类
    /// </summary>
    public partial class BotClient : IDisposable
    {
        private readonly Logger log;
        private readonly Random random;
        private readonly BotConfig config;
        private readonly XmdsNetClient client;
		private readonly IBotListViewItem mListViewCallback;

		private bool _IsInScene;         //是否进入到游戏场景中
        private string account;
        private string password;
        public int ServerId;
        public string ServerName;
        public string Host;
        public int Port;
        public string Sign;
        private SyncMessageQueue<Action> tasks = new SyncMessageQueue<Action>();

        public int LineIndex;

        public bool IsFree = true;

        public string Account { get { return account; } }
        public string Password { get { return password; } }
        public BotConfig Config { get { return config; } }
        public XmdsNetClient Client { get { return client; } }
        public Random Random { get { return random; } }
        public Pomelo.DotNetClient.NetWorkState NetState { get; private set; }

        public virtual bool IsRunning { get; }
        public virtual string RoleName
        {
            get
            {
                if (client != null && client.BattleActor != null)
                {
                    var prop = client.BattleActor.LoginData.GameServerProp as XmdsCommon.Plugin.XmdsUnitProperties;
                    return prop.ServerData.BaseInfo.name;
                }
                return "";
            }
        }
        public virtual string SceneName
        {
            get
            {
                if (client != null && client.BattleActor != null && NetState == Pomelo.DotNetClient.NetWorkState.CONNECTED)
                {
                    var prop = client.BattleClient.Layer.Data;
                    return LineIndex == 0 ? prop.ToString() : prop.Name + "(" + LineIndex + "线)";
                }
                return "";
            }
        }

        public BotClient(string user, string pswd, BotConfig cfg, IBotListViewItem callBack)
        {
            this.log = LoggerFactory.GetLogger("bot[" + user + "]");
            this.config = cfg;
            this.account = user;
            this.password = pswd;
            this.random = new Random(account.GetHashCode() + DateTime.Now.Millisecond);
			this.mListViewCallback = callBack;

			this.client = new XmdsNetClient(true);
            this._IsInScene = false;
            connect();

            this.client.GateSocket.NetWorkStateChangedEvent += callback_gt_NetWorkStateChangedEvent;
            this.client.GameSocket.NetWorkStateChangedEvent += callback_gs_NetWorkStateChangedEvent;
            this.client.OnBeginEnterScene += callback_client_OnCreateBattleClient;
            this.client.OnBattlePlayerReady += callback_client_OnBattlePlayerReady;

            this.client.GameSocket.listen<TaskUpdatePush>(callback_gs_onTaskUpdatePush);
            this.client.GameSocket.listen<BagItemUpdatePush>(callback_gs_BagItemUpdatePush);
            this.client.GameSocket.listen<ChangeAreaPush>(callback_gs_ChangeAreaPush);
        }

        public void connect(Action onConnectted = null)
        {
            string[] host = Config.LoginUrl.Split(':');
            string ip = host[0];
            int port = Convert.ToInt32(host[1]);

            Host = ip;
            Port = port;

            Client.GateSocket.connect(ip, port, 15000, (result) =>
            {
                if (result != null && result.Count > 0)
                {
                    //MessageBox.Show(Convert.ToString(result["s2c_msg"]));
                    MessageBox.Show(ip + ":" + port + "网络连接失败");
                } else if(onConnectted != null)
                {
                    onConnectted();
                }

				if(this.mListViewCallback != null)
				{
					this.mListViewCallback.Start();
				}
			});
        }

        public void SetAccount(string user, string pswd)
        {
            this.account = user;
            this.password = pswd;
        }

        private void callback_gt_NetWorkStateChangedEvent(Pomelo.DotNetClient.NetWorkState obj)
        {
            this.NetState = obj;
        }
        private void callback_gs_NetWorkStateChangedEvent(Pomelo.DotNetClient.NetWorkState obj)
        {
            this.NetState = obj;

            //网络异常状态,自动退出场景
            if(!Pomelo.DotNetClient.NetWorkState.CONNECTING.Equals(obj) || !Pomelo.DotNetClient.NetWorkState.CONNECTED.Equals(obj)) {
                this._IsInScene = false;
            }
        }
        private void callback_client_OnBattlePlayerReady(ZoneLayer arg1, ZoneActor arg2)
        {
            //arg2.SendAction(new MarkForTestBotAction());
        }

        public virtual void Start()
        {
            lock (this)
            {
                if (event_OnStart != null) event_OnStart.Invoke(this);
            }
        }
        public virtual void Stop()
        {
            lock (this)
            {
                client.Disconnect();
                if (event_OnStop != null) event_OnStop.Invoke(this);
            }
        }

        public virtual void Dispose()
        {
            event_OnStart = null;
            event_OnStop = null;
            event_OnBattleUpdate = null;
            event_OnUpdate = null;
            client.Dispose();
        }

        public virtual void Update(int intervalMS)
        {
            try
            {
                lock (this)
                {
                    tasks.ProcessMessages(do_task);
                    if (event_OnUpdate != null)
                        event_OnUpdate.Invoke(this);
                    if (client != null)
                    {
                        client.UpdateSocket(intervalMS);
                        client.DoUpdateSend();

                        //成功进入到场景里面才进行场景刷新,BindPlayer是一个点
                        if (this._IsInScene)
                            client.UpdateBattleClient(intervalMS);

                        if (client.BattleClient != null && client.BattleClient.Actor != null && event_OnBattleUpdate != null)
                        {
                            event_OnBattleUpdate.Invoke(client.BattleClient.Actor);
                        }
                        if (CurrentRegionManager != null)
                        {
                            CurrentRegionManager.Update();
                        }
                    }
                }
            }
            catch (Exception err)
            {
                log.Error(err.Message, err);
            }
        }

        public void QueueTask(Action action)
        {
            tasks.Enqueue(action);
        }

        private void do_task(Action action)
        {
            action();
        }

        public event Action<BotClient> event_OnStart;
        public event Action<BotClient> event_OnStop;
        public event Action<BotClient> event_OnUpdate;
        public event Action<ZoneActor> event_OnBattleUpdate;
    }

}