using System.Linq;
using Intrepid.Core.Tags;
using Intrepid.FSM;
using Intrepid.Structures;
using Sirenix.Utilities;
using UnityEngine;

namespace Intrepid.Core.GameState
{
    public class GameStateObject : MonoBehaviour, IState<GameState, GameStateObject>
    {
        [SerializeField] private GameState gameState;
        [SerializeField] private SceneTag[] scenes;

        private SceneTag[] Scenes { get; set; }
        private AsyncOperation[] AsyncOperations { get; set; }
        public bool IsLoadingFinished => !ShouldHaveMoreLoadRequests && AsyncOperations.All(asyncOperation => asyncOperation.isDone);

        public bool CanEnterState => true;
        public bool CanExitState => true;
        private bool ShouldHaveMoreLoadRequests { get; set; }
        
        private void Awake()
        {
            Scenes = scenes.Distinct().ToArray();
            AsyncOperations = new AsyncOperation[scenes.Length];
        }

        public GameState GetStateKey()
        {
            return gameState;
        }

        public GameStateObject Implementation()
        {
            return this;
        }

        public void OnEnterState(ParameterStore ps)
        {
            AsyncOperations[0] = Scenes[0].LoadAsync();
            ShouldHaveMoreLoadRequests = Scenes.Length > 1;
        }

        public void UpdateState()
        {
            if (!ShouldHaveMoreLoadRequests) return;
            if (!AsyncOperations[0].isDone) return;
            for (var i = 1; i < AsyncOperations.Length; i++)
            {
                AsyncOperations[i] = Scenes[i].LoadAsync();
            }
            ShouldHaveMoreLoadRequests = false;
        }

        public void OnExitState()
        {
            Scenes.ForEach(scene => scene.UnloadAsync());
            ShouldHaveMoreLoadRequests = false;
        }
    }
}