using Cirno.Scripts.Components.Actors;
using Cirno.Scripts.Enums;
using Godot;

namespace Cirno.Scripts.Components.FSM.Enemy.Turret;

public partial class TurretAlert : EnemyStateBase
{
    public override EnemyState StateId => EnemyState.Alert;

    [Export]
    public EnemyStorageModule StorageModule { get; private set; }
    
    [Export]
    public PlayerDetectionModule PlayerDetection { get; private set; }
    
    [Export]
    public GenericDamageReceiver DamageReceiver { get; private set; }
    
    
    private bool _isPlayerInRange = false;
    
    public override void EnterState()
    {
        base.EnterState();
        
        PlayerDetection.SetRange(StorageModule.Root.EnemyResource.PlayerDetectionRange);
        
        PlayerDetection.PlayerInRange += PlayerDetectionOnPlayerInRange;
        
        PlayerDetection.PlayerOutOfRange += PlayerDetectionOnPlayerOutOfRange;

        DamageReceiver.ChangeState(true);
        
        DamageReceiver.HealthProvider.ResourceDepleted += HealthProviderOnResourceDepleted;
    }
    
    private void HealthProviderOnResourceDepleted()
    {
        ChangeState(EnemyState.Dead);
    }

    private void PlayerDetectionOnPlayerOutOfRange()
    {
        _isPlayerInRange = false;
    }

    public override void ExitState()
    {
        base.ExitState();
        PlayerDetection.PlayerInRange -= PlayerDetectionOnPlayerInRange;
        
        PlayerDetection.PlayerOutOfRange -= PlayerDetectionOnPlayerOutOfRange;
        
        DamageReceiver.HealthProvider.ResourceDepleted -= HealthProviderOnResourceDepleted;
        DamageReceiver.ChangeState(false);
    }

    private void PlayerDetectionOnPlayerInRange()
    {
 
    }

    public override void PhysicsProcessState(double delta)
    {
        base.PhysicsProcessState(delta);
        if (PlayerDetection.IsPlayerInRange(StorageModule.Root.EnemyResource.ViewRange) && PlayerDetection.IsPlayerInSight())
        {

            StateMachine.SetState(EnemyState.Shooting);
            return;
        }
        
        // if player is outside disengage range, change to idle (later on, search)
        if (MainObject.GlobalPosition.DistanceTo(GameManager.Instance.PlayerPosition.Value) >=
            StorageModule.Root.EnemyResource.PlayerDisengageRange)
        {

            StateMachine.SetState(EnemyState.Idle);
            return;
        }
        
        // Set facing direction towards player
        if (PlayerDetection.LastKnownPlayerPosition.HasValue)
        {
            StorageModule.FacingDirection =
                (PlayerDetection.LastKnownPlayerPosition.Value - MainObject.GlobalPosition).Normalized(); //MainObject.Velocity.SnapToCardinal().Normalized();
            StorageModule.AimingDirection = StorageModule.FacingDirection;
        }
    }


    public override void ProcessState(double delta)
    {
        base.ProcessState(delta);
    }
}