using System;
using System.Collections.Generic;

namespace RebootKit.Engine.Foundation {
    public interface IState {
        void Enter();
        void Exit();
    }
    
    public class StateMachine<TState> where TState : class, IState {
        readonly Dictionary<Type, TState> m_States;

        IState m_ActiveState;
        
        public StateMachine() {
            m_States = new Dictionary<Type, TState>();
            m_ActiveState = null;
        }

        public StateMachine(IEnumerable<TState> states) {
            foreach (TState state in states) {
                AddState(state);
            }
        }

        public void AddState(TState state) {
            Type type = state.GetType();
            if (!m_States.TryAdd(type, state)) {
                throw new Exception($"State {type} already exists in the state machine.");
            }
        }
        
        public void TransitionTo<TStateType>() where TStateType : class, TState {
            Type type = typeof(TStateType);
            if (!m_States.TryGetValue(type, out TState newState)) {
                throw new Exception($"State {type} not found in the state machine.");
            }

            m_ActiveState?.Exit();
            m_ActiveState = newState;
            m_ActiveState.Enter();
        }

        public bool IsStateActive<TStateType>() where TStateType : class, TState => m_ActiveState != null && m_ActiveState.GetType() == typeof(TStateType);
    }
}