using CommonAI.ZoneClient;
using CommonLang;
using CommonLang.IO;
using CommonLang.Log;
using CommonLang.Vector;
using pomelo.area;
using pomelo.task;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using XmdsBattleClient.Client;
using XmdsBattleClientBot.XmdsBot;

namespace XmdsBattleClientBot.Bot
{
    // 游戏服相关 //
    partial class BotClient
    {
        public QuestManager CurrentQuestManager { get; private set; }

        public TaskUpdatePush LastTaskUpdatePush { get; private set; }

        private void callback_gs_onTaskUpdatePush(TaskUpdatePush e)
        {
            LastTaskUpdatePush = e;
            CurrentQuestManager.Refresh(e.s2c_data);
        }

        public class QuestManager
        {
           

            private readonly BotClient bot;
            private HashMap<int, QuestData> mQuests = new HashMap<int, QuestData>();

            public ICollection<QuestData> Quests { get { return mQuests.Values; } }

            internal QuestManager(BotClient bot)
            {
                this.bot = bot;
                this.Refresh(bot.PlayerData.tasks);
            }
            internal void Refresh(Tasks tasks)
            {
                if (tasks != null)
                {
                    foreach (var e in tasks.taskList)
                    {
                        var tq = BotClientManager.GetTaskTemplate(e.templateId);
                        if (tq != null)
                        {
                            QuestData td = mQuests.Get(e.templateId);
                            if (td == null)
                            {
                                td = new QuestData(bot, e.templateId, tq);
                                mQuests.Add(e.templateId, td);
                            }
                            td.UpdateTask(e.progress, e.state, e.leftTime);
                        }
                    }
                }
            }

            public QuestData GetQuest(int templateID)
            {
                return mQuests.Get(templateID);
            }


            public QuestData SeekExpectTask(BotClient.QuestData.QuestType kind, QuestData.QuestStatus status, QuestData.SeekAction action, bool random = false)
            {
                var list = new List<QuestData>(this.Quests);
                if (random)
                {
                    CUtils.RandomList<QuestData>(bot.Random, list);
                }
                foreach (var qd in list)
                {
                    if ((kind == QuestData.QuestType.INVALID || qd.Kind == kind) && qd.State == status)
                    {
                        qd.Seek(action);
                        return qd;
                    }
                }
                return null;
            }
        }

        public class QuestData
        {
            public enum NotiFyStatus : long
            {
                progress = 1L << 1,     //任务进度
                state = 1L << 2,        //任务状态
                leftTime = 1L << 3,     //剩余时间
                ALL = long.MaxValue,
            }

            //任务状态
            public enum QuestStatus : long
            {
                NONE = -2,
                NEW = -1,
                IN_PROGRESS = 0,
                CAN_FINISH = 1,
                DONE = 2,
            }

            //任务种类  (NotiFyStatus.kind)
            public enum QuestType
            {
                TRUNK = 0,          //主线
                BRANCH = 1,         //支线
                DAILY = 2,          //日常任务
                RUNNING = 3,        //跑环任务
                REWARD = 4,         //悬赏任务
                PVP = 5,            //PVP
                AREA = 6,           //区域触发任务
                FESTIVAL = 7,       //节日任务
                INVALID = int.MaxValue,
            }


            //任务类型(一个种类可以细分多个类型)
            public class EventType
            {
                public const int INVALID = -1;
                public const int KillMonster = 1;        //杀怪
                public const int InterActiveNpc = 2;     //与NPC互动
                public const int InterActiveItem = 3;    //与道具互动
                public const int KillCollect = 4;        //杀怪拾取道具
                public const int Convoy = 5;             //护送
                public const int Guard = 6;              //守护
                public const int Area = 7;
                public const int KillPlayer = 8;
                public const int FISH =     15;         // 钓鱼获得道具
                public const int Challenge = 25;
                public const int ConqueringtheDemons = 26;
                public const int Steal = 27;
                public const int RefineSoul = 28;
                public const int CatchPet = 29;
                public const int Treasure = 30;
                public const int GETMEDAL = 31;
                public const int LEVEL_UP = 32;
            }

            private readonly Dictionary<string, object> mLocalData;
            private readonly BotClient bot;

            public BotClient Bot { get { return bot; } }
            public int TemplateID { get; private set; }
            public QuestType Kind { get; private set; }
            public int SubType { get; private set; }
            public QuestStatus State { get; private set; }
            public List<int> Progress { get; private set; }
            public int LeftTime { get; private set; }
            public int SubmitNpcId { get; private set; }
            public int AcceptNpcId { get; private set; }
            public string TargetId { get; private set; }
            public string Name { get; private set; }

            internal QuestData(BotClient bot, int templateID, Dictionary<string, object> fields)
            {
                this.bot = bot;
                this.TemplateID = templateID;
                this.mLocalData = new Dictionary<string, object>(fields);
                this.Kind = (QuestType)GetIntParam("Kind");
                this.SubType = GetIntParam("Type");
                this.SubmitNpcId = GetIntParam("CompleteNpc");
                this.AcceptNpcId = GetIntParam("GiveNpc");
                this.TargetId = GetStringParam("TargetID");
                this.Name = GetStringParam("Name");
            }

            public override string ToString()
            {
                return string.Format("{0}({1})", Name, TemplateID);
            }

            internal void UpdateTask(List<int> progress, int state, int leftTime)
            {
                long s = 0;
                if ((int)this.State != state)
                {
                    s |= (int)NotiFyStatus.state;
                    State = (QuestStatus)(state);
                }
                if (this.Progress != progress)
                {
                    s |= (int)NotiFyStatus.progress;
                    this.Progress = progress;
                }

                if (this.LeftTime != leftTime)
                {
                    s |= (int)NotiFyStatus.leftTime;
                    this.LeftTime = leftTime;
                }
            }

            public int GetIntParam(string name)
            {
                if (mLocalData == null)
                {
                    return -1;
                }
                object ret;
                int ret_int = 0;
                if (mLocalData.TryGetValue(name, out ret))
                {
                    int.TryParse(ret.ToString(), out ret_int);
                }
                return ret_int;
            }

            public string GetStringParam(string name)
            {
                if (mLocalData == null)
                {
                    return null;
                }
                object ret;
                if (mLocalData.TryGetValue(name, out ret))
                {
                    return ret.ToString();
                }
                else
                {
                    return null;
                }
            }
            //-------------------------------------------------------------------------------------------------------------------
            public delegate void SeekAction(QuestData quest, SeekInfo info);
            public class SeekInfo
            {
                public readonly QuestData quest;
                public int areaId;
                public int pointId;
                public int npcTemplateID;
                public bool attack;
                public Vector2 MoveTo;
                public string FunID;
                public bool ShowDetail;
                public bool NoWay;
                internal SeekInfo(QuestData quest)
                {
                    this.quest = quest;
                }
            }
            private void StartSeek(SeekAction action, int areaId, int pointId, int npcTemplateID, string funID, bool attack)
            {
                var layer = bot.CurrentZoneLayer;
                if (layer != null && layer.IsLoaded)
                {
                    if (areaId == layer.Data.ID)
                    {
                        var point = bot.CurrentZoneLayer.GetFlag<ZoneEditorPoint>(pointId.ToString());
                        if (point != null)
                        {
                            action.Invoke(this, new SeekInfo(this)
                            {
                                areaId = areaId,
                                pointId = pointId,
                                npcTemplateID = npcTemplateID,
                                attack = attack,
                                MoveTo = new Vector2(point.X, point.Y),
                            });
                            return;
                        }
                        var npc = bot.CurrentNpcManager.GetNpcByTemplateID(npcTemplateID);
                        if (npc != null)
                        {
                            action.Invoke(this, new SeekInfo(this)
                            {
                                areaId = areaId,
                                pointId = pointId,
                                npcTemplateID = npcTemplateID,
                                attack = attack,
                                MoveTo = new Vector2(npc.X, npc.Y),
                            });
                            return;
                        }
                        if (!string.IsNullOrEmpty(funID))
                        {
                            action.Invoke(this, new SeekInfo(this) { FunID = funID, });
                            return;
                        }
                        action.Invoke(this, new SeekInfo(this)
                        {
                            areaId = areaId,
                            pointId = pointId,
                            npcTemplateID = npcTemplateID,
                            attack = attack,
                            NoWay = true,
                        });
                    }
                    else
                    {
                        bot.Client.GameSocket.playerHandler.queryLoadWayRequest(areaId, pointId.ToString(), (ex, msg) =>
                        {
                            if (ex == null)
                            {
                                var point = bot.CurrentZoneLayer.GetFlag(msg.s2c_pointId);
                                if (point != null)
                                {
                                    action.Invoke(this, new SeekInfo(this)
                                    {
                                        areaId = areaId,
                                        pointId = pointId,
                                        npcTemplateID = npcTemplateID,
                                        attack = attack,
                                        MoveTo = new Vector2(point.X, point.Y),
                                    });
                                    return;
                                }
                            }
                            action.Invoke(this, new SeekInfo(this)
                            {
                                areaId = areaId,
                                pointId = pointId,
                                npcTemplateID = npcTemplateID,
                                attack = attack,
                                NoWay = true,
                            });
                        });
                    }
                }
            }
            private void Goto(SeekAction action, string funID)
            {
                action.Invoke(this, new SeekInfo(this) { FunID = funID, });
            }
            private void ShowQuestDetail(SeekAction action)
            {
                action.Invoke(this, new SeekInfo(this) { ShowDetail = true, });
            }
            //-------------------------------------------------------------------------------------------------------------------
            public void Seek(SeekAction action)
            {
                if (State == QuestData.QuestStatus.NEW)
                {
                    int acceptNpcId = GetIntParam("GiveNpc");
                    if (acceptNpcId > 0)
                    {
                        //int moveType = MoveData.MOVE_TYPE_NPCTALK;
                        int areaId = GetIntParam("StartScene");
                        int pointId = GetIntParam("StartPoint");
                        this.StartSeek(action, areaId, pointId, acceptNpcId, null, false);
                    }
                    else
                    {
                        //弹出可接任务详情
                        //                         Dictionary<string, string> p = new Dictionary<string, string>();
                        //                         p.Add("id", TemplateID.ToString());
                        this.ShowQuestDetail(action);
                    }
                }
                else if (State == QuestData.QuestStatus.IN_PROGRESS)
                {
                    int areaId = GetIntParam("DoScene");
                    string funId = GetStringParam("FunID");
                    if (areaId == 0)
                    {
                        if (!string.IsNullOrEmpty(funId))
                        {
                            //                             Dictionary<string, string> p = new Dictionary<string, string>();
                            //                             p.Add("id", funId);
                            this.Goto(action, funId);
                        }
                        else
                        {
                            this.ShowQuestDetail(action);
                        }
                    }
                    else
                    {
                        int pointId = GetIntParam("DoPoint");
                        int targetId = GetIntParam("TargetID");
                        //int moveType = 0;
                        bool attack = false;
                        //DataMgr.Instance.UserData.AutoFight = false;
                        if (SubType == QuestData.EventType.InterActiveNpc)
                        {
                            //moveType = MoveData.MOVE_TYPE_NPCTALK;
                        }
                        else if (SubType == EventType.KillMonster || SubType == EventType.KillCollect)
                        {
                            //moveType = MoveData.MOVE_TYPE_ATTACK_MONSTER;
                            attack = true;
                        }
                        this.StartSeek(action, areaId, pointId, targetId, funId, attack);
                        //DataMgr.Instance.UserData.StartSeek(areaId, pointId, moveType, targetId);
                    }

                }
                else if (State == QuestData.QuestStatus.CAN_FINISH)
                {
                    int submitNpcId = GetIntParam("CompleteNpc");
                    if (submitNpcId > 0)
                    {
                        //DataMgr.Instance.UserData.AutoFight = false;
                        //string targetId = submitNpcId.ToString();
                        //int moveType = MoveData.MOVE_TYPE_NPCTALK;
                        int areaId = GetIntParam("SubmitScene");
                        int pointId = GetIntParam("SubmitPoint");
                        //DataMgr.Instance.UserData.StartSeek(areaId, pointId, moveType, targetId);
                        this.StartSeek(action, areaId, pointId, submitNpcId, null, false);
                    }
                    else
                    {
                        //弹出可接任务详情
                        //                         Dictionary<string, string> p = new Dictionary<string, string>();
                        //                         p.Add("id", TemplateID.ToString());
                        //EventManager.Fire("Event.ShowQuestDetail", p);
                        this.ShowQuestDetail(action);
                    }
                }
            }
            public string GetTargetString()
            {
                string str = GetStringParam("Prompt");
                str = str.Replace("%s", GetIntParam("Quantity").ToString());
                return str;
            }
            public bool IsInterActiveNpc(int npcTemplateId)
            {
                return (SubType == QuestData.EventType.InterActiveNpc &&
                        State == QuestData.QuestStatus.IN_PROGRESS &&
                        GetIntParam("TargetID") == npcTemplateId);
            }
            public string GetFormatProgress()
            {
                int total = GetIntParam("Quantity");
                //progress为0和Quantity为0表示没有进度
                if (Progress[0] == 0 && total == 0 && State != QuestStatus.IN_PROGRESS ||
                    (SubType == EventType.InterActiveNpc && total == 1))
                {
                    return null;
                }
                else
                {
                    string format = "({0}/{1})";
                    string ret = string.Format(format, this.Progress, total);
                    return ret;
                }
            }

        }

    }

}