using CommonAI.Zone;
using CommonAI.Zone.Helper;
using CommonAI.ZoneClient;
using ET;
using ET.EventType;
using Sirenix.Utilities;
using System;
using XmdsCommon.Plugin;

public class BattleUnit : BattleObject
{
    public BattleUnit() { }
    public ZoneUnit ZUnit { get { return ZoneObject as ZoneUnit; } }

    private EventDispatcher<UnitActionStatus, object> actionChangeHandler;

    public override void OnAwake(ZoneObject zo)
    {
        base.OnAwake(zo);

        actionChangeHandler = new();
        registerActionHandler();

        var zu = zo as ZoneUnit;
        zu.OnActionChanged += OnActionChanged;
        zu.OnSkillActionChanged += OnSkillActionChanged;
        zu.OnHPChanged += OnHPChanged;
        zu.OnMPChanged += OnMPChanged;
        zu.OnMaxHPChanged += OnMaxHPChanged;
        zu.OnMaxMPChanged += OnMaxMPChanged;
        zu.OnLaunchSkill += OnLaunchSkill;
        zu.OnBuffAdded += OnBuffAdded;
        zu.OnBuffRemoved += OnBuffRemoved;
        zu.OnBuffChanged += OnBuffChanged;
        zu.OnRemoveBuffByOverlayLevel += OnRemoveBuffByOverlayLevel;
        zu.OnActionSubStatusChanged += OnActionSubStatusChanged;
    }

    protected virtual void OnRemoveBuffByOverlayLevel(ZoneUnit unit, ZoneUnit.BuffState buff)
    {
        throw new NotImplementedException();
    }

    protected virtual void OnBuffChanged(ZoneUnit unit, ZoneUnit.BuffState buff)
    {
        throw new NotImplementedException();
    }

    protected virtual void OnBuffRemoved(ZoneUnit unit, ZoneUnit.BuffState buff)
    {
        throw new NotImplementedException();
    }

    protected virtual void OnBuffAdded(ZoneUnit unit, ZoneUnit.BuffState buff)
    {
        throw new NotImplementedException();
    }

    private static uint groupId = 1;
    protected static uint GroupId()
    {
        return ++ groupId;
    }

    protected virtual void OnLaunchSkill(ZoneUnit _, ZoneUnit.SkillState __, UnitLaunchSkillEvent ___)
    {
        CommonAI.ZoneClient.ZoneUnit.ISkillAction action = ZUnit.CurrentSkillAction;
        if(action == null)
        {
            Log.Warning("object's currentSkillAction = null, cannot launch skill");
            return;
        }
        SkillTemplate skillTemplate = action.SkillData;
        var curActionIndex = action.CurrentActionIndex;
        if (skillTemplate.ActionQueue.Count <= curActionIndex)
        {
            Log.Error("Enter Skill state error> ({0})>CurrentActionIndex>{1}", skillTemplate.TemplateID, curActionIndex);
            return;
        }
        //Log.Debug($"OnLaunchSkill({Id}), skill({skillTemplate.TemplateID}), actionIndex:{curActionIndex}");
        
        if (skillTemplate.IsSingleAction)
        {
            UnitActionData actdata = skillTemplate.ActionQueue[curActionIndex];
            if (actdata.ActionName.IsNullOrWhitespace())
            {
                Log.Debug($"ActionName is null @skill({skillTemplate.TemplateID}), actionIndex:{curActionIndex}");
                return;
            }
            var duration = action.ActionTimeArray != null ? action.ActionTimeArray[0] : actdata.TotalTimeMS;
            EventSystem.Instance.Publish<PlayAnimatorEvent>(PlayAnimatorEvent.Static.Clone(
                Id,
                AnimatorEventType.Skill,
                actdata.ActionName,
                duration,
                action.ActionSpeed,
                0,
                actdata.IsCycAction, actdata.ActionAudioName)
            );
        }
        else
        {
            float speed = 1.0f;
            bool isFrist = true;
            for (int i = curActionIndex; i < skillTemplate.ActionQueue.Count; i++)
            {
                UnitActionData item = skillTemplate.ActionQueue[i];
                if (item.ActionName.IsNullOrWhitespace())
                {
                    Log.Debug($"ActionName is null @skill({skillTemplate.TemplateID}), actionIndex:{curActionIndex}");
                    return;
                }

                if (action.LaunchEvent != null)
                {
                    speed = action.LaunchEvent.action_speed;
                    if (action.LaunchEvent.action_speed_add != null && i < action.LaunchEvent.action_speed_add.Length)
                    {
                        speed += action.LaunchEvent.action_speed_add[i];
                    }
                }

                EventSystem.Instance.Publish<PlayAnimatorEvent>(PlayAnimatorEvent.Static.Clone(
                    Id,
                    AnimatorEventType.Skill,
                    item.ActionName,
                    action.ActionTimeArray[i],
                    speed, GroupId(),
                    item.IsCycAction,
                    isFrist ? item.ActionAudioName : ""));

                if(!item.ActionAudioName.IsNullOrWhitespace())
                {
                    if (isFrist)
                    {
                        isFrist = false;
                    }
                    else
                    {
                        Log.Error("not implements multiAction audio");
                    }
                }
            }
        }
    }

    protected virtual void OnMaxMPChanged(ZoneUnit unit, int oldMaxMP, int newMaxMP)
    {
        throw new NotImplementedException();
    }

    protected virtual void OnMPChanged(ZoneUnit unit, int oldMP, int newMP)
    {
        throw new NotImplementedException();
    }

    protected virtual void OnMaxHPChanged(ZoneUnit unit, int oldMaxHP, int newMaxHP)
    {
        OnHPChanged();
    }
    protected virtual void OnHPChanged(ZoneUnit unit, int oldHP, int newHP)
    {
        OnHPChanged();
    }
    private void OnHPChanged()
    {
        var prop = ZUnit.Info.Properties as XmdsUnitProperties;
        if (prop != null)
        {
            if(prop.GameStatusType == XmdsUnitProperties.StatusType.SpecialElite)
            {
                var hp = ZUnit.HP;
                var pg = (float)ZUnit.HP * 100 / ZUnit.MaxHP;
                EventSystem.Instance.Publish<HPRefresh>(HPRefresh.Static.Clone(HPRefresh.Index.Tower, pg, hp));
                Log.Debug($"tower({ZUnit.ObjectID}@{ZUnit.Info.Name}) hp: {ZUnit.HP}/{ZUnit.MaxHP}");
            }
            else if(prop.GameStatusType == XmdsUnitProperties.StatusType.SpecialBoss)
            {
                var hp = ZUnit.HP;
                var pg = (float)ZUnit.HP * 100 / ZUnit.MaxHP;
                EventSystem.Instance.Publish<HPRefresh>(HPRefresh.Static.Clone(HPRefresh.Index.Boss, pg, hp));
                Log.Debug($"Boss({ZUnit.ObjectID}) hp: {ZUnit.HP}/{ZUnit.MaxHP}");
            }
        }
        //Log.Debug($"hp({ZUnit.ObjectID}) change: {ZUnit.HP}");
    }

    protected virtual void OnSkillActionChanged(ZoneUnit unit, ZoneUnit.SkillState skill, byte index)
    {
        //技能状态
    }

    protected virtual void OnActionChanged(ZoneUnit unit, UnitActionStatus status, object evt)
    {
        //Log.Debug($"ActionChange({Id}): {status}, zobject status:{ZUnit.CurrentState}");
        if(!actionChangeHandler.Notify(status, evt))
        {
            Log.Error($"unhandle action changed: {status}");
        }
    }
    protected virtual void OnActionSubStatusChanged(ZoneUnit unit, byte status, object evt)
    {

    }
    private void registerActionHandler()
    {
        actionChangeHandler.AddListener(UnitActionStatus.Idle, (_) => {
            EventSystem.Instance.Publish<PlayAnimatorEvent>(PlayAnimatorEvent.Static.Clone(Id, AnimatorEventType.Idle));
        });

        var move = actionChangeHandler.AddListener(UnitActionStatus.Move, (o) => {
            EventSystem.Instance.Publish<PlayAnimatorEvent>(PlayAnimatorEvent.Static.Clone(Id, AnimatorEventType.Run));
        });
        actionChangeHandler.AddListener(UnitActionStatus.Chaos, move);
        actionChangeHandler.AddListener(UnitActionStatus.ServerSyncMove, move);
        actionChangeHandler.AddListener(UnitActionStatus.Escape, move);

        var stun = actionChangeHandler.AddListener(UnitActionStatus.Stun, (o) => { });
        actionChangeHandler.AddListener(UnitActionStatus.HitMove, stun);
        actionChangeHandler.AddListener(UnitActionStatus.Dead, (o) => {
            Log.Debug($"Unit({Id}) dead");
            EventSystem.Instance.Publish<PlayAnimatorEvent>(PlayAnimatorEvent.Static.Clone(
                Id, AnimatorEventType.Dead ));
            var launcheffect = ZUnit.Info.DeadActionEffect;
            if (launcheffect != null)
            {
                EventSystem.Instance.Publish<PlayEffectEvent>(PlayEffectEvent.Static.Clone(launcheffect, Id, CommonLang.Geometry.Vector3.Zero));
            }
            //TODO: 过几秒后,自行清理尸体
        });
        actionChangeHandler.AddListener(UnitActionStatus.Damage, (o) => { });
        actionChangeHandler.AddListener(UnitActionStatus.Pick, (o) => { });
        actionChangeHandler.AddListener(UnitActionStatus.Spawn, (o) => { });
        actionChangeHandler.AddListener(UnitActionStatus.ChargeAtkMove, (o) => { });
        actionChangeHandler.AddListener(UnitActionStatus.ChargeAtkIdle, (o) => { });
        actionChangeHandler.AddListener(UnitActionStatus.DaZuo, (o) => { });
        actionChangeHandler.AddListener(UnitActionStatus.DaZuoRecoveryAttr, (o) => { });
        actionChangeHandler.AddListener(UnitActionStatus.ChuanGongA, (o) => { });
        actionChangeHandler.AddListener(UnitActionStatus.ChuanGongB, (o) => { });
        actionChangeHandler.AddListener(UnitActionStatus.BuffLockStateAction, (o) => { });
        actionChangeHandler.AddListener(UnitActionStatus.HomeBack, (o) => { });
        actionChangeHandler.AddListener(UnitActionStatus.ClearYaoQi, (o) => { });
        actionChangeHandler.AddListener(UnitActionStatus.PetLock, (o) => { });
        actionChangeHandler.AddListener(UnitActionStatus.BreakShield, (o) => { });
        actionChangeHandler.AddListener(UnitActionStatus.Transport, (o) => { });
        actionChangeHandler.AddListener(UnitActionStatus.Skill, (o) => { });
    }

}