using Intrepid.Core;
using Intrepid.Diagnostics;
using Intrepid.GameManagers;
using Intrepid.Gameplay.Entities.Player.ActionBelt.Events;
using Intrepid.Integration.Input;
using Intrepid.Integration.Persistence.Events;
using Intrepid.Structures;
using Intrepid.Utilities;
using UnityEngine;

namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
{
    public class SentinelStateSavingStation : SentinelState
    {
        [GroupInjections, SerializeField] private AnimationClip savingStation;
        [GroupInjections, SerializeField, Range(0, 5)] private float minSavingStationDuration = 3f;

        private Timer Timer { get; } = new();
        private bool IsSavingGameIOFinished { get; set; }
        
        public override SentinelStateType GetStateKey()
        {
            return SentinelStateType.SavingStation;
        }

        protected override void Subscriptions()
        {
            Subscribe<SavingGameDataBeginEvent>(_ =>
            {
                DLogger.LogDebug("saving game IO process is going to start!");
            });
            Subscribe<SavingGameDataEndEvent>(_ =>
            {
                DLogger.LogDebug("saving game IO process is over!");
                IsSavingGameIOFinished = true;
            });
        }

        public override void RunOnFirstFrameOnly()
        {
            InputService.Instance.ChangeInputSchema(InputSchema.None);
            base.RunOnFirstFrameOnly();
        }

        protected override void RunOnEnter(ParameterStore ps)
        {
            var deploymentPoint = ps.Get<Vector3>(SentinelConstants.Parameters.DeploymentPoint);
            Brain.Entity.DesiredVelocity = Vector2.zero;
            Brain.Entity.Position = deploymentPoint;
            Brain.Entity.ChangeOrientation(Vector2.down);
            Brain.Entity.ModelAnimation.Play(savingStation);
            Timer.Start();
            IsSavingGameIOFinished = false;
            GameManager.Instance.GameSlotPersistenceService.SaveCurrentGameData();
        }

        protected override void RunOnExit()
        {
            Timer.Stop();
            IsSavingGameIOFinished = false;
            Proxy.Instance.EventBus.Raise(new ActionBeltShowEvent());
        }

        public override void RunOnUpdate()
        {
            if (Timer.IsNotRunning) return;
            Timer.Update(Timer.ScaledTime);
            if (Timer.Check(minSavingStationDuration) && IsSavingGameIOFinished)
            {
                DLogger.LogDebug($"Total saving time: {Timer.ElapsedTime:F2}s");
                Timer.Stop();
                IsSavingGameIOFinished = false;
                InputService.Instance.ChangeInputSchema(InputSchema.Sentinel);
                Brain.ChangeState(SentinelStateType.Idle);
            }
        }
    }
}