using Level.Role;
using UnrealSharp;
using UnrealSharp.Attributes;
using UnrealSharp.BusyRabbit;
using UnrealSharp.CoreUObject;
using UnrealSharp.Engine;
using UnrealSharp.GameplayAbilities;
using UnrealSharp.GameplayTags;
using UnrealSharp.SpinePlugin;
namespace GameAbilitySystem.Ability.Role.Fox;
[UClass]
public class UFoxUltimate : UBusyGameAbility
{
    protected bool bIsEventBinded = false;
    protected ABusyFoxRole? Owner = null;
    protected UFoxUltimateDataAsset? FoxData = null;
    protected UBusyAbilitySystemComponent? ASC = null;
    protected FActiveGameplayEffectHandle CastStateHandle;
    protected FActiveGameplayEffectHandle SkillStateHandle;
    protected FActiveGameplayEffectHandle AccelerateHandle;  // 大招移动速度增加的Effect
    protected FActiveGameplayEffectHandle SprintHandle;      // 大招三阶移速再次增加的Effect
    [UFunction()]
    protected void OnGamePlayTagAddOrRemove(FGameplayTag tag, int isAdd)
    {
        if (isAdd == 0 && !IsActive)
        {
            CommitAbilityCooldown();
        }
    }
    /// 
    /// 初始化技能依赖的属性
    /// 
    /// false->初始化失败
    protected bool InitAbilityOnce()
    {
        Owner = OwningActorFromActorInfo as ABusyFoxRole;
        if (Owner == null) return false;
        FoxData = Data as UFoxUltimateDataAsset;
        ASC = AbilitySystemLibrary.GetAbilitySystemComponent(Owner) as UBusyAbilitySystemComponent;
        if (FoxData == null || ASC == null) return false;
        if (bIsEventBinded) return true;
        TDelegate Delegate = new TDelegate();
        Delegate.BindUFunction(this, "OnGamePlayTagAddOrRemove");
        Owner.BindGameplayTagAddOrRemove(FoxData.SecondStageCastTag, Delegate);
        Owner.BindGameplayTagAddOrRemove(FoxData.LastStageCastTag, Delegate);
        bIsEventBinded = true;
        return true;
    }
    /// 
    /// 获取当前大招的阶段
    /// 
    /// 
    protected int GetCurrentAbilityStage()
    {
        if (ASC == null || FoxData == null) return 0;
        if (ASC.HasMatchingGameplayTag(FoxData.LastStageCastTag))
        {
            return 3;
        }
        if (ASC.HasMatchingGameplayTag(FoxData.SecondStageCastTag))
        {
            return 2;
        }
        else if (ASC.HasMatchingGameplayTag(FoxData.FirstStageCastTag))
        {
            return 1;
        }
        return 0;
    }
    protected override void ActivateAbilityFromEvent(FGameplayEventData eventData)
    {
        base.ActivateAbilityFromEvent(eventData);
        if (!InitAbilityOnce())
        {
            EndAbility();
            return;
        }
        if (Owner == null || !CommitAbilityCost(Owner))
        {
            EndAbility();
            return;
        }
        int stage = GetCurrentAbilityStage();
        if (stage != 0)
        {
            TriggerAbility(stage);
        }
        else
        {
            EndAbility();
            return;
        }
    }
    /// 
    /// 当被授予技能时,立刻获得可释放第一段大招的常驻Tag
    /// 
    /// 
    /// 
    public override void OnGiveAbility(FGameplayAbilityActorInfo actorInfo, FGameplayAbilitySpec spec)
    {
        base.OnGiveAbility(actorInfo, spec);
        InitAbilityOnce();
        if (FoxData == null || ASC == null) return;
        UBusyGameplayEffectSubSystem EffectSubSystem = GetGameInstanceSubsystem();
        if (EffectSubSystem == null) return;
        UGameplayEffect effect = EffectSubSystem.GetTagGrantEffectWithDuration(
            new FGameplayTagContainer(FoxData.FirstStageCastTag),
            new FGameplayTagContainer(), 0
        );
        FGameplayEffectSpecHandle handle = UBusyAscLibrary.MakeGameplayEffectSpecHandle(ASC, effect, 1);
        ASC.ApplyGameplayEffectSpecToSelf(handle);
    }
    protected bool ApplayCastEffect(FGameplayTag CastTag)
    {
        UBusyGameplayEffectSubSystem EffectSubSystem = GetGameInstanceSubsystem();
        if (ASC == null || EffectSubSystem == null || FoxData == null) return false;
        ASC.RemoveActiveGameplayEffect(CastStateHandle);
        if (CastTag.IsValid)
        {
            UGameplayEffect cast_effect = EffectSubSystem.GetTagGrantEffectWithDuration(
                new FGameplayTagContainer(CastTag),
                new FGameplayTagContainer(), FoxData.RecastWindow
            );
            FGameplayEffectSpecHandle CastSpecHandle = UBusyAscLibrary.MakeGameplayEffectSpecHandle(ASC, cast_effect, 1);
            CastStateHandle = ASC.ApplyGameplayEffectSpecToSelf(CastSpecHandle);
        }
        return true;
    }
    protected bool ApplyEffect(FGameplayTag stateTag, FGameplayTag CastTag)
    {
        UBusyGameplayEffectSubSystem EffectSubSystem = GetGameInstanceSubsystem();
        if (ASC == null || EffectSubSystem == null || FoxData == null) return false;
        
        ApplayCastEffect(CastTag);
        ASC.RemoveActiveGameplayEffect(SkillStateHandle);
        UGameplayEffect state_effect = EffectSubSystem.GetTagGrantEffectWithDuration(
            new FGameplayTagContainer(stateTag),
            new FGameplayTagContainer(), 0
        );
        FGameplayEffectSpecHandle stateSpecHandle = UBusyAscLibrary.MakeGameplayEffectSpecHandle(ASC, state_effect, 1);
        SkillStateHandle = ASC.ApplyGameplayEffectSpecToSelf(stateSpecHandle);
        return true;
    }
    protected bool TriggerAbility(int stage)
    {
        if (FoxData == null) return false;
        if (stage == 1)
        {
            if (!ApplyEffect(FoxData.FirstStageTag, FoxData.SecondStageCastTag)) return false;
        }
        else if (stage == 2)
        {
            if (!ApplyEffect(FoxData.SecondStageTag, new FGameplayTag())) return false;
        }
        else if(stage == 3)
        {
            if (!ApplyEffect(FoxData.LastStageTag, new FGameplayTag())) return false;
        }
        PlayAnimation(stage);
        return true;
    }
    protected string GetAnimationName(FVector2D direction, int stage)
    {
        string animation_name_prefix = "";
        if (direction.X >= 0)
        {
            animation_name_prefix = "Ultimate/Right/";
        }
        else
        {
            animation_name_prefix = "Ultimate/Left/";
        }
        if (stage == 1)
        {
            return animation_name_prefix + "UltimateStage1";
        }
        else if (stage == 2)
        {
            return animation_name_prefix + "UltimateStage2";
        }
        else if (stage == 3)
        {
            return animation_name_prefix + "UltimateStage3";
        }
        return "";
    }
    [UFunction()]
    protected void OnAnimationComplete(UTrackEntry Entry)
    {
        Entry.AnimationComplete.Remove(OnAnimationComplete);
        if (ASC != null)
        {
            if (ASC.HasMatchingGameplayTag(FoxData.LastStageTag))
            {
                CommitAbilityCooldown();
            }
            ASC.RemoveActiveGameplayEffect(SkillStateHandle);
        }
        EndAbility();
    }
    [UFunction()]
    protected void OnTailBeginOverlay(UPrimitiveComponent OverlappedComponent, AActor OtherActor,
        UPrimitiveComponent OtherComp, int OtherBodyIndex, bool bFromSweep, FHitResult SweepResult)
    {
        if (ASC == null || FoxData == null) return;
        bool bIsStage2 = ASC.HasMatchingGameplayTag(FoxData.SecondStageTag);
        if (bIsStage2 && !ASC.HasMatchingGameplayTag(FoxData.LastStageCastTag))
        {
            ApplayCastEffect(FoxData.LastStageCastTag);
        }
    }
    [UFunction()]
    protected void OnAnimationEvent(UTrackEntry Entry, FSpineEvent Event)
    {
        if (ASC == null || FoxData == null || Owner == null) return;
        if (Event.Name == "OnSpeedChange")
        {
            AccelerateHandle = MakeAccelerate(FoxData.LastStageSprintSpeedFactor, 1);
        }
        else if (Event.Name == "OnSpeedReset")
        {
            ASC.RemoveActiveGameplayEffect(AccelerateHandle);
        }
        else if (Event.Name == "OnDamageBegin")
        {
            Owner.SetTailCollisionEnabled(true);
            Owner.FoxTailCollision.OnComponentBeginOverlap.Add(OnTailBeginOverlay);
        }
        else if (Event.Name == "OnDamageEnd")
        {
            Owner.SetTailCollisionEnabled(false);
            Owner.FoxTailCollision.OnComponentBeginOverlap.Remove(OnTailBeginOverlay);
        }
    }
    protected FActiveGameplayEffectHandle MakeAccelerate(float SpeedFactor, float TotalTime)
    {
        GetAbilityEffectSpecHandle("Accelerate", ASC, 1, out FGameplayEffectSpecHandle handle);
        AbilitySystemLibrary.AssignTagSetByCallerMagnitude(
            handle, UBusyGameplayLibrary.RequestGameplayTag("Effect.Factor"),  SpeedFactor
        );
        AbilitySystemLibrary.AssignTagSetByCallerMagnitude(
            handle, UBusyGameplayLibrary.RequestGameplayTag("Effect.Duration"), TotalTime
        );
        return ApplyGameplayEffectSpecToOwner(handle);
    }
    
    protected bool PlayAnimation(int stage)
    {
        FVector2D AbilityDirection = new FVector2D(0, 1);
        if (UGameplayStatics.GetPlayerController(0) is ALevelPlayerController PC)
        {
            PC.GetCursorDirection(out AbilityDirection);
        }
        string AnimationName = GetAnimationName(AbilityDirection, stage);
        if (AnimationName == "") return false;
        USpineSkeletonAnimationComponent Animation = Owner.SpineAnimationComponent;
        UTrackEntry AnimEntry = Animation.SetAnimation(0, AnimationName, false);
        AnimEntry.AnimationEvent.Add(OnAnimationEvent);
        AnimEntry.AnimationComplete.Add(OnAnimationComplete);
        float TotalTime = AnimEntry.GetAnimationEnd();
        if (stage == 1) MakeAccelerate(FoxData.FirstStageSpeedFactor, TotalTime);
        else if (stage == 2) MakeAccelerate(FoxData.SecondStageSpeedFactor, TotalTime);
        else if (stage == 3) MakeAccelerate(FoxData.LastStageNormalSpeedFactor, TotalTime);
        Owner.MovementComponent.ActivateSprint(AbilityDirection, TotalTime);
        return true;
    }
}
// function FoxUltimate:ctor()
//     self.ultimate_phase = 1  -- 大招阶段
//     self.active_recast_handle = nil
//     self.active_accelerate_handle = nil
//     self.overlap_delegate_handle = nil
//     self.tag_add_or_remove_delegate = nil
// end
// function FoxUltimate:OnAnimationComplete(entry)
//     local new_phase = self.ultimate_phase + 1
//     if new_phase > 3 then
//         self.ultimate_phase = 1
//     else
//         self.ultimate_phase = new_phase
//     end
//     print("FoxUltimate:OnAnimationComplete", self.ultimate_phase)
//     if not self.asc:HasMatchingGameplayTag(self.recast_tag) then
//         self.ultimate_phase = 1
//         self:K2_CommitAbilityCooldown(false, false)
//     end
//     entry.AnimationComplete:Clear()
//     entry.AnimationEvent:Clear()
//     self:K2_EndAbility()
// end