using System.Collections.Generic;
using System.Reflection;
using Godot;
using Godot.Collections;

namespace Cirno.Scripts.Components.FSM;

public abstract partial class BaseState<TKey, TType> : Node, IState<TKey, TType>
    where TKey : notnull
    where TType : Node
{
    public virtual TKey StateId { get; }
    public IStateMachine<TKey, TType> StateMachine => _stateMachine;

    private IStateMachine<TKey, TType> _stateMachine;

    public TType MainObject => _stateMachine.MainObject;

    [Export]
    private Array<Node> _moduleNodes = [];

    protected readonly List<IModule<TKey, TType>> _modules = [];
    
    public virtual void Init(IStateMachine<TKey, TType> machine)
    {
        _stateMachine = machine;

        foreach (var node in _moduleNodes)
        {
            if (node is not IModule<TKey, TType> module) continue;
            _modules.Add(module);
            module.Init(_stateMachine);
        }
    }

    protected void ChangeState(TKey newState)
    {
        _stateMachine.SetState(newState);
    }

    public virtual void EnterState()
    {
        foreach (var module in _modules)
        {
            module.EnterState(StateId);
        }
    }

    public virtual void ExitState()
    {
        foreach (var module in _modules)
        {
            module.ExitState(StateId);
        }
    }

    public virtual void ProcessState(double delta)
    {
        foreach (var module in _modules)
        {
            module.Process(delta);
        }
        //_modules.ForEach(module => module.Process(delta));
    }

    public virtual void PhysicsProcessState(double delta)
    {
        foreach (var module in _modules)
        {
            module.PhysicsProcess(delta);
        }
        //_modules.ForEach(module => module.PhysicsProcess(delta));
    }
}