using CommonAI.Zone.Instance;
using CommonAI.Zone.ZoneEditor;
using CommonLang;
using CommonLang.Log;
using CommonLang.Property;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using XmdsCommon.Plugin;
using XmdsCommonServer.Message;
using XmdsCommonServer.Plugin.Units;

namespace XmdsCommonServer.Plugin.Quest
{
    public class QuestScriptManager
    {
        private static Logger log = LoggerFactory.GetLogger("QuestScriptManager");

        private static HashMap<string, Type> QuestTypes = new HashMap<string, Type>();

        private static HashMap<int, Type> QuestTypeTypes = new HashMap<int, Type>();

        static QuestScriptManager()
        {
            
        }

        public static void Init()
        {
            LoadQuestDll();
        }

        private static void LoadQuestDll()
        {
            if(QuestTypeTypes.Count > 0)
            {
                return;
            }
            try
            {
                Type base_type = typeof(QuestScript);
                foreach (Type sub_type in ReflectionUtil.GetNoneVirtualSubTypes(base_type))
                {
                    if (sub_type.IsSubclassOf(base_type))
                    {
                        var attr = PropertyUtil.GetAttribute<QuestListenAttribute>(sub_type);
                        if (attr != null)
                        {
                            QuestTypes.Add(attr.quest_id, sub_type);
                        }

                        var attr_qtype = PropertyUtil.GetAttribute<QuestTypeListenAttribute>(sub_type);
                        if (attr_qtype != null)
                        {
                            QuestTypeTypes.Add((int)attr_qtype.quest_type, sub_type);
                        }
                    }
                }
            }
            catch (Exception err)
            {
                log.Error("LoadQuestDll : " + err);
            }
        }


        public static QuestScript CreateQuestScript(string quest_id, XmdsInstancePlayer player)
        {
            var q = player.GetQuest(quest_id);
            QuestScript ret = null;
            try
            {
                int taskType = XmdsQuestData.GetTaskType(q);

                string qua = q.Attributes.Get("SecretTransfer");

                Type stype;
                if (QuestTypes.TryGetValue(quest_id, out stype) || QuestTypeTypes.TryGetValue(taskType, out stype))
                {
                    ret = ReflectionUtil.CreateInstance(stype) as QuestScript;
                }

                if (!string.IsNullOrEmpty(qua))
                {
                    string[] s = qua.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
                    int sceneID = int.Parse(s[0]);
                    if (sceneID == (player.Parent as EditorScene).Data.GetID())
                    {
                        ZoneRegion region = player.Parent.getFlagAs<ZoneRegion>(s[1]);
                        int playerCount = region.getObjectsCountInRegion<InstancePlayer>((ip) =>
                        {
                            return ip == player;
                        });

                        if (playerCount <= 0)
                        {
                            if (ret == null)
                            {
                                ret = new Quest_Simple();
                            }
                            ZoneRegion.UnitEnterHandler handler = new ZoneRegion.UnitEnterHandler((rg, u) =>
                            {
                                if (u == ret.Player)
                                {
                                    // 传送
                                    var q1 = ret.Player.GetQuest(quest_id);
                                    if (q1 != null && !XmdsQuestData.IsTargetComplete(q1))
                                    {
                                        int transSceneID = XmdsQuestData.GetTargetSceneID(q1);
                                        string transPoint = XmdsQuestData.GetTargetScenePoint(q1);
                                        TransUnitEventB2R evt = new TransUnitEventB2R();
                                        evt.playerId = ret.Player.PlayerUUID;
                                        evt.SceneID = transSceneID;
                                        ret.Player.queueEvent(evt);
                                    }

                                }
                            });

                            ret.DisposeEvent += (script) =>
                            {
                                region.OnUnitEnter -= handler;
                            };
                            ret.StartEvent += (script) =>
                            {
                                region.OnUnitEnter += handler;
                            };
                        }
                    }
                }
                if (ret != null)
                {
                    player.SetQuestScript(quest_id, taskType, ret);
                }
            }
            catch (Exception err)
            {
                log.Error(string.Format("Try CreateQuestScript [{0}] Error :{1} ", quest_id, err.ToString()));
            }


            return ret;
        }

        public static void ClearQuestScript(string quest_id, XmdsInstancePlayer player)
        {
            player.RemoveQuestScript(quest_id);
        }

        public static void QuestStatusChanged(string quest_id, XmdsInstancePlayer player, string key, string value)
        {
            var qs = player.GetQuestScript(quest_id);
            if (qs != null)
            {
                qs.OnStatusChanged(key, value);
            }
        }
    }

    /// <summary>
    /// 标记类,处理接取任务事件
    /// </summary>
    [AttributeUsage(AttributeTargets.Class)]
    public class QuestListenAttribute : System.Attribute
    {
        readonly public string quest_id;
        public QuestListenAttribute(string quest_id)
        {
            this.quest_id = quest_id;
        }
    }

    /// <summary>
    /// 标记类,处理接取任务事件
    /// </summary>
    [AttributeUsage(AttributeTargets.Class)]
    public class QuestTypeListenAttribute : System.Attribute
    {
        readonly public XmdsQuestData.TaskType quest_type;
        public QuestTypeListenAttribute(XmdsQuestData.TaskType q_type)
        {
            this.quest_type = q_type;
        }
    }
}