using Intrepid.FSM;
using Intrepid.Integration.Input;
using Intrepid.Theatre.BackStage;
using Intrepid.Theatre.Curtain;
using Intrepid.Utilities;
using UnityEngine;

namespace Intrepid.Core.GameState
{
    public class GameStateMachine : Identification, IBackStageProcessor
    {
        [GroupConfigurations, SerializeField] private GameState bootstrapState;
        [GroupConfigurations, SerializeField] private BackStageService backStageService;
        
        private FStateMachine<GameState, GameStateObject> StateMachine { get; } = new ();
        private GameState GameStateToChange { get; set; }
        private BackStageService BackStageService => backStageService;
        private BackStageProcessorAggregator BackStageProcessorAggregator { get; set; }

        private void Awake()
        {
            foreach (var gameStateObject in gameObject.GetComponentsInChildren<GameStateObject>())
            {
                StateMachine.AddState(gameStateObject);
            }
            StateMachine.InitializeWith(bootstrapState);
            BackStageProcessorAggregator = new BackStageProcessorAggregator(this);
        }

        private void Start()
        {
            StateMachine.Start();
        }

        private void Update()
        {
            BackStageService.UpdateCurtains();
            StateMachine.GetCurrentState().Implementation().UpdateState();
        }

        public void ChangeTo(GameState gameState, CurtainTypeTag curtainType, BackStageProcessorAggregator processorAggregator)
        {
            if (BackStageService.KickProcess(curtainType, Id, BackStageProcessorAggregator, processorAggregator))
            {
                GameStateToChange = gameState;
            }
        }

        public bool IsProcessFinished => StateMachine.GetCurrentState().Implementation().IsLoadingFinished;
        
        public void AfterOpened()
        {
        }

        public void BeforeOpening()
        {
        }

        public void AfterClosed()
        {
            StateMachine.ChangeState(GameStateToChange);
        }

        public void BeforeClosing()
        {
            InputService.Instance.ChangeInputSchema(InputSchema.None);
        }
    }
}