using MonoGame.FourEngine;
using Raycast.Win32.Services;
using System.Collections.Generic;
using static MonoGame.FourEngine.ServiceLocator;

namespace Raycast.Win32.Entities
{
    partial class Enemy
    {
        public enum EnemyState
        {
            Idle,
            Hurt,
            Shoot,
            Rush,
            Chase,
            Death
        }

        public EnemyState State
        {
            get => _state;
            set
            {
                if (!_isEnabled) return;

                // Remove old state
                if (Components.Contains(_stateComponent))
                {
                    _stateComponent.OnExit();
                    Components.Remove(_stateComponent);
                }

                _state = value;

                // Add new state
                if (StateHandlers != null && StateHandlers.TryGetValue(value, out _stateComponent))
                {
                    _stateComponent.OnEnter();
                    Components.Add(_stateComponent);
                }
            }
        }

        private EnemyState _state;
        private EnemyStateBase _stateComponent;
        private bool _isEnabled;

        protected Dictionary<EnemyState, EnemyStateBase> StateHandlers { get; private set; }

        protected void InitializeStateMachine()
        {
            StateHandlers = new Dictionary<EnemyState, EnemyStateBase>
            {
                { EnemyState.Idle, new IdleState(this) },
                { EnemyState.Hurt, new HurtState(this) },
                { EnemyState.Shoot, new ShootState(this) },
                { EnemyState.Rush, new RushState(this) },
                { EnemyState.Chase, new ChaseState(this) },
                { EnemyState.Death, new DeathState(this) },
            };
            _isEnabled = true;
            State = default;
        }

        protected void ShutdownStateMachine()
        {
            _isEnabled = false;
            if (Components.Contains(_stateComponent))
            {
                _stateComponent.OnExit();
                Components.Remove(_stateComponent);
            }
        }

        protected abstract class EnemyStateBase : Component
        {
            protected Enemy Enemy { get; }

            protected IPathfindingService Pathfinding => LazyResolver<IPathfindingService>.Resolve();

            public EnemyStateBase(Enemy enemy)
            {
                Enemy = enemy;
            }

            public virtual void OnEnter() { }
            public virtual void OnExit() { }

            protected void GoToState(EnemyState state) => Enemy.State = state;
            protected void GoToNextState() => Enemy.State = Enemy.Decide();
        }
    }
}