using System;
using Intrepid.Utilities;
using Sirenix.OdinInspector;
using UnityEngine;

namespace Intrepid.Gameplay.Entities.Player.PDA.UI
{
    public class PDALoadingProcessUI : MonoBehaviour
    {
        [SerializeField] private PDABlockageUI blockage;
        [Title("a safe measure to let loading animation and stuff happen")]
        [SerializeField] private float minimalLoadingTime = .75f;

        public bool AnimationRunning => blockage.AnimationRunning;
        public bool IsLoading { get; private set; }
        private Func<bool> IsStillLoading { get; set; } = () => true;
        private Timer Timer { get; } = new();
        private bool EagerFinish { get; set; }
        
        public void UpdateLoadingProcess()
        {
            if (Timer.IsNotRunning) return;
            Timer.Update(Time.deltaTime);
            if (!Timer.Check(minimalLoadingTime) || IsStillLoading.Invoke()) return;
            Timer.Stop();
            if (EagerFinish)
            {
                IsLoading = false;
                BlockageUnblock();
            }
            else
            {
                FinishLoading();
            }
        }

        public void StraightBlock()
        {
            blockage.StraightBlock();
        }

        public void BlockageBlock()
        {
            blockage.Block(() => { });
        }

        public void StartLoadingNoAnimation(Func<Func<bool>> executor, bool eagerFinish = false)
        {
            EagerFinish = eagerFinish;
            Timer.Start();
            IsLoading = true;
            IsStillLoading = executor();
        }

        public void StartLoading(Func<Func<bool>> executor, bool replaceCurrentExecution = false, bool eagerFinish = false)
        {
            EagerFinish = eagerFinish;
            Timer.Start();
            blockage.Bump();
            if (IsLoading)
            {
                if (replaceCurrentExecution)
                {
                    // if it is already loading replace current execution
                    IsStillLoading = executor();
                }
                return;
            }
            blockage.Block(() =>
            {
                IsStillLoading = executor();
            });
            IsLoading = true;
        }

        public void FinishLoading()
        {
            blockage.Unblock(() => IsLoading = false);
        }

        public void BlockageUnblock()
        {
            blockage.Unblock(() => { });
        }
    }
}