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

public class BattleUnit : BattleObject
{
    public BattleUnit() { }
    public ZoneUnit ZUnit { get { return ZoneObject as ZoneUnit; } }
    public bool IsDead { get { return ZUnit.CurrentState == UnitActionStatus.Dead; } }

    private EventDispatcher<UnitActionStatus, object> actionChangeHandler;
    public int Vip = 0;

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

        actionChangeHandler = new();
        registerActionHandler();

        var zu = zo as ZoneUnit;
        zu.OnActionChanged += OnActionChanged;
        zu.OnSkillActionChanged += (ZoneUnit unit, ZoneUnit.SkillState skill, byte index) => { };
        zu.OnHPChanged += (ZoneUnit unit, int oldHP, int newHP)=> { OnHPChanged(); };
        zu.OnMPChanged += (ZoneUnit unit, int oldMaxMP, int newMaxMP) => { };
        zu.OnMaxHPChanged += (ZoneUnit unit, int oldHP, int newHP) => { OnHPChanged(); };
        zu.OnMaxMPChanged += (ZoneUnit unit, int oldMaxMP, int newMaxMP)=> { };
        zu.OnLaunchSkill += OnLaunchSkill;
        zu.OnBuffAdded += (ZoneUnit unit, ZoneUnit.BuffState buff) => {
            EventSystem.Instance.Publish(BuffChangeEvent.Static.Clone(Id, buff, BuffChangeEvent.BuffOP.Add));
        };
        zu.OnBuffRemoved += (ZoneUnit unit, ZoneUnit.BuffState buff) => {
            EventSystem.Instance.Publish(BuffChangeEvent.Static.Clone(Id, buff, BuffChangeEvent.BuffOP.Remove));
        };
        zu.OnBuffChanged += (ZoneUnit unit, ZoneUnit.BuffState buff) => {
            EventSystem.Instance.Publish(BuffChangeEvent.Static.Clone(Id, buff, BuffChangeEvent.BuffOP.Change));
        };
        zu.OnRemoveBuffByOverlayLevel += (ZoneUnit unit, ZoneUnit.BuffState buff) => { };
        zu.OnActionSubStatusChanged += OnActionSubStatusChanged;
    }
    public override void OnSleep()
    {
        base.OnSleep();
        Vip = 0;
    }

    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.Clone(
                Id,
                PlayAnimatorEvent.AniType.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.Clone(
                    Id,
                    PlayAnimatorEvent.AniType.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");
                    }
                }
            }
        }
    }

    private void OnHPChanged()
    {
        if (ZUnit.Info.Properties is XmdsUnitProperties prop)
        {
            //Log.Debug($"hp({ZUnit.TemplateID}) change: {ZUnit.HP}");
            if (prop.GameStatusType == XmdsUnitProperties.StatusType.SpecialElite)
            {
                var hp = ZUnit.HP;
                var pg = hp * 100f / ZUnit.MaxHP;
                EventSystem.Instance.Publish(HPRefresh.Clone(HPRefresh.Index.Tower, pg, prop.ServerData.BaseInfo.name, hp.ToString()));
                return;
            }
            else if (prop.GameStatusType == XmdsUnitProperties.StatusType.SpecialBoss)
            {
                RefreshBossHPBar(prop);
                return;
            }

            if (prop.ShowHPBanner)
            {
                EventSystem.Instance.Publish(SyncUnitHpEvent.Clone(Id, ZUnit.HP * 100f / ZUnit.MaxHP));
            }
        }
    }

    //有3个HP血条,找合适的条条显示
    private static List<ZoneUnit> pgList = new();
    public static void Reset()
    {
        pgList.Clear();
    }
    private void RefreshBossHPBar(XmdsUnitProperties prop)
    {
        var hp = ZUnit.HP;
        int hide = -1;
        for(var i = 0; i < pgList.Count; i++)
        {
            var unit = pgList[i];
            if(hide >= 0)
            {
                hp = unit.HP;
                prop = unit.Info.Properties as XmdsUnitProperties;
                EventSystem.Instance.Publish(HPRefresh.Clone(HPRefresh.Index.Boss1 + i - 1, hp * 100f / unit.MaxHP, prop.ServerData.BaseInfo.name, hp.ToString()));
            }
            else if(unit.TemplateID == ZUnit.TemplateID)
            {
                /*if(hp <= 0)
                {
                    hide = i;
                    EventSystem.Instance.Publish(HPRefresh.Clone(HPRefresh.Index.Boss1 + pgList.Count - 1, 0, "", "", false));
                }
                else*/
                {
                    EventSystem.Instance.Publish(HPRefresh.Clone(HPRefresh.Index.Boss1 + i, hp * 100f / ZUnit.MaxHP, prop.ServerData.BaseInfo.name, hp.ToString()));
                    return;
                }
            }
        }
        if(hide >= 0)
        {
            pgList.RemoveAt(hide);
            return;
        }

        if (pgList.Count >= 4)
        {
            Log.Error("wtf, more than 4 boss.");
            return;
        }

        if(hp <= 0)
        {
            return;
        }

        pgList.Add(ZUnit);
        EventSystem.Instance.Publish(HPRefresh.Clone(HPRefresh.Index.Boss1 + pgList.Count-1, hp * 100f / ZUnit.MaxHP, prop.ServerData.BaseInfo.name, hp.ToString()));
    }

    protected virtual void OnActionChanged(ZoneUnit unit, UnitActionStatus status, object evt)
    {
        //Log.Debug($"ActionChange({unit.Info.TemplateID}): {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)
    {
        //Log.Debug($"OnActionSubStatusChanged({unit.Info.TemplateID}): {status}<= zobject status:{ZUnit.CurrentSubState}");
    }
    private void registerActionHandler()
    {
        actionChangeHandler.AddListener(UnitActionStatus.Idle, (_) => {
            EventSystem.Instance.Publish(PlayAnimatorEvent.Clone(Id, PlayAnimatorEvent.AniType.Idle));
        });

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

        var stun = actionChangeHandler.AddListener(UnitActionStatus.Stun, (o) => {
            //TODO: 判断没有FROZEN的BUFF状态,才进行stun的动作
        });
        actionChangeHandler.AddListener(UnitActionStatus.HitMove, stun);
        actionChangeHandler.AddListener(UnitActionStatus.Dead, (o) => {
            EventSystem.Instance.Publish(UnitDead.Clone(Id));
        });
        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) => { });
        actionChangeHandler.AddListener(UnitActionStatus.Rebirth, (o) => {
            EventSystem.Instance.Publish(UnitRebirth.Clone(Id));
        });
    }

}