using CommonAI.Zone;
using CommonAI.Zone.Instance;
using CommonAI.Zone.ZoneEditor;
using CommonLang;
using CommonLang.Log;
using CommonLang.Vector;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using XmdsCommonServer.Plugin.Scene;
using XmdsCommonServer.Plugin.Units;

namespace XmdsCommonServer.Plugin.Quest
{
    /// <summary>
    /// 任务脚本子类
    /// </summary>
    public abstract class QuestScript
    {
        protected readonly static Logger log = LoggerFactory.GetLogger("QuestScript");
        private string m_QuestID;
        //private int m_QuestType;

        private XmdsInstancePlayer m_Player;
        private XmdsServerScene m_Zone;
        private XmdsVirtual_Player m_Virtual;

        /// <summary>
        /// 当前场景
        /// </summary>
        public XmdsServerScene Zone { get { return m_Zone; } }
        /// <summary>
        /// 触发的任务ID
        /// </summary>
        public string QuestID { get { return m_QuestID; } }

        /// <summary>
        /// 触发的任务类型
        /// </summary>
        //public int QuestType { get { return m_QuestType; } }
        /// <summary>
        /// 触发任务的玩家实体
        /// </summary>
        public XmdsInstancePlayer Player { get { return m_Player; } }
        /// <summary>
        /// 触发任务的玩家虚体
        /// </summary>
        public XmdsVirtual_Player Virtual { get { return m_Virtual; } }
        /// <summary>
        /// 当前AOI
        /// </summary>
        public XmdsPlayerAOI AOI { get { return m_Player.AoiStatus as XmdsPlayerAOI; } }

        Action<QuestScript> mOnStart;
        Action<QuestScript> mOnDispose;
        public event Action<QuestScript> DisposeEvent { add { mOnDispose += value; } remove { mOnDispose -= value; } }
        public event Action<QuestScript> StartEvent { add { mOnStart += value; } remove { mOnStart -= value; } }


        //---------------------------------------------------------------------------------------------------
        internal void Init(string questID, int questType, XmdsInstancePlayer player)
        {
            this.m_QuestID = questID;
            this.m_Player = player;
            this.m_Zone = player.Parent as XmdsServerScene;
            this.m_Virtual = player.Virtual as XmdsVirtual_Player;
        }
        internal void Dispose()
        {
            this.OnDispose();
            if (mOnDispose != null)
            {
                mOnDispose.Invoke(this);
            }
            this.m_QuestID = null;
            this.m_Player = null;
            this.m_Zone = null;
            this.m_Virtual = null;
        }
        internal void Start()
        {
            this.OnStart();
            if (mOnStart != null)
            {
                mOnStart.Invoke(this);
            }
        }
        //---------------------------------------------------------------------------------------------------

        /// <summary>
        /// 脚本开始回调
        /// </summary>
        protected abstract void OnStart();

        /// <summary>
        /// 脚本结束回调
        /// </summary>
        protected abstract void OnDispose();

        /// <summary>
        /// 返回true表示处理完成后不传递到其他QuestScrpt中
        /// </summary>
        /// <returns></returns>
        public virtual bool TryDoAction(ObjectAction act)
        {
            return false;
        }
        //---------------------------------------------------------------------------------------------------
        #region API

        /// <summary>
        /// 任务失败
        /// </summary>
        /// <param name="reason">原因</param>
        public void QuestFailed(string reason = "")
        {
            Zone.QuestAdapter.DoDropQuest(Player.PlayerUUID, QuestID, reason);
        }
        /// <summary>
        /// 任务完成
        /// </summary>
        /// <param name="reason">原因</param>
        public void QuestAccomplish(string reason = "")
        {
            Zone.QuestAdapter.DoCommitQuest(Player.PlayerUUID, QuestID, reason);
        }

        public virtual void OnStatusChanged(string key, string v)
        {

        }

        /// <summary>
        /// 玩家进入AOI
        /// </summary>
        /// <param name="can_see_me"></param>
        /// <param name="can_see_other"></param>
        public void PlayerEnterAOI(bool can_see_me = false, bool can_see_other = false)
        {
            XmdsPlayerAOI aoi = new XmdsPlayerAOI(Player, can_see_me, can_see_other);
            Player.setAoiStatus(aoi);
        }

        /// <summary>
        /// 玩家离开AOI
        /// </summary>
        public void PlayerLeaveAOI()
        {
            Player.setAoiStatus(null);
        }

        /// <summary>
        /// 添加若干单位在区域范围内
        /// </summary>
        /// <param name="region_name">区域名字</param>
        /// <param name="unit_template_id">模板ID</param>
        /// <param name="count">数量</param>
        /// <param name="force">Force</param>
        /// <param name="aoi">是否在AOI</param>
        /// <param name="unit_name">名字</param>
        /// <param name="level">等级</param>
        /// <param name="attack_to">出生后A到此处</param>
        /// <returns></returns>
        public InstanceUnit[] AddUnitsInRegion(string region_name, int unit_template_id, int count, int force, bool aoi = true, string unit_name = null, int level = 0, string attack_to = null)
        {
            InstanceUnit[] ret = new InstanceUnit[count];
            var region = Zone.GetEditFlag(region_name) as ZoneRegion;
            if (region != null)
            {
                for (int i = count - 1; i >= 0; --i)
                {
                    var pos = region.getRandomPos(Zone.RandomN);
                    var unit = AddUnit(pos, unit_template_id, force, aoi, unit_name, level, attack_to);
                    ret[i] = unit;
                }
            }
            else
            {
                log.Error("Region not exist : " + region_name);
            }
            return ret;
        }
        /// <summary>
        /// 添加一个单位
        /// </summary>
        /// <param name="region_name">区域名字</param>
        /// <param name="unit_template_id">模板ID</param>
        /// <param name="force">Force</param>
        /// <param name="aoi">是否在AOI</param>
        /// <param name="unit_name">名字</param>
        /// <param name="level">等级</param>
        /// <param name="attack_to">出生后A到此处</param>
        /// <returns></returns>
        public InstanceUnit AddUnitInRegion(string region_name, int unit_template_id, int force, bool aoi = true, string unit_name = null, int level = 0, string attack_to = null)
        {
            var region = Zone.GetEditFlag(region_name) as ZoneRegion;
            if (region != null)
            {
                return AddUnit(region.Pos, unit_template_id, force, aoi, unit_name, level, attack_to);
            }
            else
            {
                log.Error("Region not exist : " + region_name);
                return null;
            }
        }

        /// <summary>
        /// 添加一个单位
        /// </summary>
        /// <param name="pos">坐标</param>
        /// <param name="unit_template_id">模板ID</param>
        /// <param name="force">Force</param>
        /// <param name="aoi">是否在AOI</param>
        /// <param name="unit_name">名字</param>
        /// <param name="level">等级</param>
        /// <param name="attack_to">出生后A到此处</param>
        /// <returns></returns>
        public InstanceUnit AddUnit(IVector2 pos, int unit_template_id, int force, bool aoi = true, string unit_name = null, int level = 0, string attack_to = null)
        {
            InstanceUnit unit = Zone.AddUnit(unit_template_id, "", (byte)force, level, pos.X, pos.Y, CMath.RandomAngle(Zone.RandomN));
            if (unit != null)
            {
                if (aoi) unit.setAoiStatus(Player.AoiStatus);
                if (unit is InstanceGuard && attack_to != null)
                {
                    InstanceGuard guard = unit as InstanceGuard;
                    ZoneWayPoint flag = Zone.GetEditFlag(attack_to) as ZoneWayPoint;
                    if (flag != null)
                    {
                        guard.attackTo(flag);
                    }
                }
            }
            else
            {
                log.Error("Create unit error : " + unit_template_id);
            }
            return unit;
        }

        #endregion
        //---------------------------------------------------------------------------------------------------
    }

    public class Quest_Simple : QuestScript
    {
        protected override void OnDispose() {}
        protected override void OnStart() {}
    }
}