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

namespace Cirno.Scripts.Components.FSM.Enemy;

public partial class Idle : EnemyStateBase
{
    public override EnemyState StateId => EnemyState.Idle;
    
    // Scan for player, move to alert if found
    // Receive damage, move to alert if received
    
    [Export]
    public EnemyStorageModule StorageModule { get; private set; }
    
    [Export]
    public PlayerDetectionModule PlayerDetection { get; private set; }
    
    [Export]
    public GenericDamageReceiver DamageReceiver { get; private set; }

    // public override void Init(IStateMachine<EnemyState, CharacterBody2D> machine)
    // {
    //     base.Init(machine);
    // } 
    private bool _isPlayerInRange = false;
    
    public override void EnterState()
    {
        base.EnterState();
        PlayerDetection.SetRange(StorageModule.Root.EnemyResource.PlayerDetectionRange);
        
        _isPlayerInRange = PlayerDetection.IsPlayerInRange(StorageModule.Root.EnemyResource.ViewRange);
        
        PlayerDetection.PlayerInRange += PlayerDetectionOnPlayerInRange;
        
        PlayerDetection.PlayerOutOfRange += PlayerDetectionOnPlayerOutOfRange;

        DamageReceiver.ChangeState(true);
        
        DamageReceiver.HealthProvider.ResourceDepleted += HealthProviderOnResourceDepleted;
        
        DamageReceiver.HealthProvider.ResourceDecreased += HealthProviderOnResourceDecreased;
    }

    private void HealthProviderOnResourceDecreased(float oldvalue, float newvalue, float maxvalue)
    {
        StorageModule.AiState = AiState.Enabled;
        ChangeState(EnemyState.Alert);
    }

    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.HealthProvider.ResourceDecreased -= HealthProviderOnResourceDecreased;
        DamageReceiver.ChangeState(false);
        
    }

    private void PlayerDetectionOnPlayerInRange()
    {
        _isPlayerInRange = true;
        GD.Print("Player In Range");
    }

    public override void PhysicsProcessState(double delta)
    {
        base.PhysicsProcessState(delta);
        if (StorageModule.AiState is AiState.Enabled && _isPlayerInRange)
        {
            if (PlayerDetection.IsPlayerInSight())
            {
                StateMachine.SetState(EnemyState.Alert);
            }
        }
    }

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