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

namespace Cirno.Scripts.Components.FSM.Player.Hacking;

public partial class HackingActive : PlayerStateBase
{
    public override PlayerState StateId => PlayerState.Active;
    private Vector2 _movementDirection { get; set; }

    public Vector2 FacingDirection
    {
        get => _storageModule.FacingDirection;
        private set => _storageModule.FacingDirection = value;
    }

    [Export] public int Speed { get; set; } = 45;
    [Export] public int StrafeSpeed { get; set; } = 35;
    //[Export] public float Acceleration = 8f;
    //[Export] public float Deceleration = 8f;

    [ExportCategory("Providers")] [Export] private PlayerWeaponProvider _weaponProvider;
    [Export] private PlayerAnimationProvider _animationProvider;
    //[Export] private PlayerCrosshairProvider _crosshairProvider;
    [Export] private PlayerHitboxSpriteProvider _hitboxSpriteProvider;

    [Export] private InputProvider _inputProvider;

    [Export] private PlayerDamageReceiver _damageReceiver;
    //[Export] private ActivationProvider _activationProvider;

    //[Export] private InteractionController _interactionController;

    [Export] private PlayerStorageModule _storageModule;

    private bool _isStrafing;

    public int MovementSpeed => _isStrafing ? StrafeSpeed : Speed;

    private CharacterBody2D _player;

    //private Hud _hud;

    public override void Init(IStateMachine<PlayerState, CharacterBody2D> machine)
    {
        base.Init(machine);

        //_hud = Hud.Instance;

        _damageReceiver.Death += () => { ChangeState(PlayerState.Dead); };

        _damageReceiver.HealthDecreased += (value, newValue, maxValue) =>
        {
            _animationProvider.Blink();
            //_hud.UpdateHealth(value, maxValue);
        };

        _damageReceiver.ShieldDecreased += (value, newValue, maxValue) =>
        {
            _animationProvider.PlayShieldAnimation();
            //_hud.UpdateShield(value, maxValue);
        };

        _damageReceiver.Init(StateMachine);

        _damageReceiver.RefillHealth();
        _damageReceiver.RefillShield();

        //_activationProvider.Init(MainObject);

        _weaponProvider.Init(MainObject);
    }

    public override void EnterState()
    {
        base.EnterState();
        // enable sprite
        // enable crosshair
        //_crosshairProvider.Show();
        _animationProvider.ShowSprite();
        _damageReceiver.Enabled = true;
        //_activationProvider.Enabled = true;
        //_interactionController.Enabled = true;
        
        //_accelerationPerSecond = Speed / Acceleration;
        //_decelerationPerSecond = Speed / Deceleration;
    }

    public override void ExitState()
    {
        base.ExitState();
        _animationProvider.SetAnimationSpeed(Vector2.Zero);
        //_animationProvider.SetAnimation(Vector2.Zero);
        //_crosshairProvider.Hide();
        _hitboxSpriteProvider.Hide();

        _damageReceiver.Enabled = false;
        //_activationProvider.Enabled = false;
        //_interactionController.Enabled = false;
    }

    //private float _accelerationPerSecond;
    //private float _decelerationPerSecond;
    
    public override void PhysicsProcessState(double delta)
    {
        // Reset at start of frame
        //MainObject.Velocity = Vector2.Zero;

        // Process modules
        base.PhysicsProcessState(delta);
        
        if (_isStrafing)
        {
            // Instant movement at strafe speed
            MainObject.Velocity = _movementDirection * StrafeSpeed;
        }
        else
        {
            MainObject.Velocity = _movementDirection * Speed;
            
            // Vector2 targetVelocity = _movementDirection * Speed;
            //
            // if (_movementDirection != Vector2.Zero)
            // {
            //     MainObject.Velocity = MainObject.Velocity.MoveToward(targetVelocity, Acceleration * (float)delta);
            // }
            // else
            // {
            //     MainObject.Velocity = MainObject.Velocity.MoveToward(Vector2.Zero, Deceleration * (float)delta);
            // }
        }
        
        //MainObject.Velocity += _movementDirection * MovementSpeed;

        MainObject.MoveAndSlide();
    }

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

        _movementDirection = _inputProvider.GetMovementInput().Normalized();
        _isStrafing = _inputProvider.GetStrafePressed();

        // Toggle visibility of the hitbox sprite based on strafing
        _hitboxSpriteProvider.SetVisibility(_isStrafing);

        //var rightStickInput = _inputProvider.GetAimInput().Normalized();

        // Update Facing Direction
        // if (!_isStrafing)
        // {
        // if (rightStickInput.Length() > 0.1f) // If the right stick is moved
        // {
        //     FacingDirection = rightStickInput;
        // }
        // else if (_movementDirection != Vector2.Zero) // Fall back to movement direction
        // {
        //     FacingDirection = _movementDirection;
        // }
        // }
        
        FacingDirection = Vector2.Up;

        _animationProvider.SetAnimationSpeed(MainObject.Velocity);
        _animationProvider.SetAnimation(FacingDirection);

        //HandleWeaponSwitch();
        _weaponProvider.Update(delta);
        
        //_crosshairProvider.UpdatePosition(FacingDirection);

        HandleShoot();

        HandleInteraction();
        // FindInteractable();

        // _crosshair.Position = CalculateCrosshairPosition();

        if (_inputProvider.GetInventoryJustPressed())
        {
            GameManager.Instance.ChangeState(GameState.Inventory);
        }

        if (_inputProvider.GetPauseJustPressed())
        {
            //CallDeferred(MethodName.PauseDeferred);
            PauseDeferred();
        }
    }

    private void PauseDeferred()
    {
        GameManager.Instance.Pause();
    }

    private void HandleShoot()
    {
        if (_inputProvider.GetReloadJustPressed())
        {
            _weaponProvider.Reload();
            return;
        }
        
        if (!_inputProvider.GetShootPressed()) return;
        _weaponProvider.Shoot(this.FacingDirection);
    }

    private void HandleInteraction()
    {
        //_activationProvider.HandleInteraction();
    }

    private void HandleWeaponSwitch()
    {
        if (_inputProvider.GetWeaponNextJustPressed())
        {
            _weaponProvider.NextWeapon();
        }
        else if (_inputProvider.GetWeaponPreviousJustPressed())
        {
            _weaponProvider.PreviousWeapon();
        }
    }
}