using System.Collections.Generic;
using Godot;

namespace Cirno.Scripts.Components.Actors;

public partial class AnimationHandler : ActorModule
{
    [Export]
    public AnimatedSprite2D _animatedSprite { get; protected set; }
    
    protected Actor _parent;
    
    public bool IsDestroyed => _parent.IsDestroyed;
    
    public override void Init(Actor parent)
    {
        _parent = parent;
        _parent.OnDeath += ParentOnOnDeath;
        // var children = GetChildren();
        // foreach (var child in children) {
        //     if (child is InputProvider inputProvider) 
        //     {
        //         _inputProviders.Add(inputProvider);
        //     }
        // }
    }

    protected virtual void ParentOnOnDeath()
    {
        _animatedSprite.SpeedScale = 0;
        _animatedSprite.Hide();
    }

    public override void Update(double delta)
    {
        if (IsDestroyed) return;
        
        var direction = _parent.FacingDirection; //GetSnappedDirection();
        
        if (_parent.Velocity.Length() > 0)
        {
            _animatedSprite.Play("walk_" + DirectionToString(direction));
            _animatedSprite.SpeedScale = 1;
        }
        else
        {
            //_animatedSprite.Play("idle_" + DirectionToString(direction));
            _animatedSprite.Play("walk_" + DirectionToString(direction));
            _animatedSprite.SpeedScale = 0;
        }
    }

    public override void PhysicsUpdate(double delta)
    {
        
    }

    protected virtual string DirectionToString(Vector2 direction)
    {
        var angle = Mathf.RadToDeg(direction.Angle());
        angle = Mathf.PosMod(angle, 360);

        if (angle >= 337.5 || angle < 22.5) return _directionsTable[FacingDirection.Right];
        if (angle >= 22.5 && angle < 67.5) return _directionsTable[FacingDirection.DownRight];
        if (angle >= 67.5 && angle < 112.5) return _directionsTable[FacingDirection.Down];
        if (angle >= 112.5 && angle < 157.5) return _directionsTable[FacingDirection.DownLeft];
        if (angle >= 157.5 && angle < 202.5) return _directionsTable[FacingDirection.Left];
        if (angle >= 202.5 && angle < 247.5) return _directionsTable[FacingDirection.UpLeft];
        if (angle >= 247.5 && angle < 292.5) return _directionsTable[FacingDirection.Up];
        if (angle >= 292.5 && angle < 337.5) return _directionsTable[FacingDirection.UpRight];

        return _directionsTable[FacingDirection.Up];
    }

    protected readonly Dictionary<FacingDirection, string> _directionsTable = new()
    {
        { FacingDirection.Right, "right" },
        { FacingDirection.Left, "left" },
        { FacingDirection.Up, "up" },
        { FacingDirection.Down, "down" },
        { FacingDirection.UpLeft, "up_left" },
        { FacingDirection.UpRight, "up_right" },
        { FacingDirection.DownLeft, "down_left" },
        { FacingDirection.DownRight, "down_right" }
    };

    protected enum FacingDirection
    {
        Up,
        Down,
        Left,
        Right,
        UpRight,
        UpLeft,
        DownRight,
        DownLeft
    }
}