using System.Collections.Generic;
using Godot;

namespace Cirno.Scripts.Components.FSM;

public abstract partial class IsoStateMachineBase<TKey, TType> : Node, IStateMachine<TKey, TType>
    where TKey : notnull
    where TType : Node
{
    public Dictionary<TKey, IState<TKey, TType>> States { get; set; } = new();
    public TKey CurrentStateIndex { get; set; }
    public IState<TKey, TType> CurrentState => States[CurrentStateIndex];
    public abstract TKey InitialState { get; protected set; }

    private TType _mainObject;
    public TType MainObject => _mainObject;
    
    public override void _Ready()
    {
        _mainObject = this.GetParent<TType>();
        var children = GetChildren();

        foreach (var child in children)
        {
            if (child is IState<TKey, TType> state)
            {
                States.Add(state.StateId, state);
                state.Init(this);
            }
        }
        SetState(InitialState);
    }
    
    public void SetState(TKey stateId)
    {
        if (CurrentStateIndex is not null)
        {
            CurrentState.ExitState();
        }
        CurrentStateIndex = stateId;
        CurrentState.EnterState();
    }
    
    public override void _Process(double delta)
    {
        if (CurrentStateIndex is null) return;
        CurrentState.ProcessState(delta);
    }

    public override void _PhysicsProcess(double delta)
    {
        if (CurrentStateIndex is null) return;
        CurrentState.PhysicsProcessState(delta);
    }
}