using System;
using System.Collections;
using Intrepid.Gameplay.Codex.UI.Controllers;
using Intrepid.Utilities;
using UnityEngine;
using UnityEngine.UI;

namespace Intrepid.Gameplay.Entities.Player.ActionBelt.UI
{
    public class CodexActionBeltActivationProgressControllerUI : CodexControllerUI
    {
        [GroupInjections, SerializeField] private Slider progressSlider;

        [GroupConfigurations, SerializeField, Range(0.01f, 1f)]
        private float cancelReturnDuration = .5f;

        private Coroutine returnRoutine;

        private void Show()
        {
            if (progressSlider.IsNull()) return;
            progressSlider.gameObject.SetActive(true);
        }

        private void Hide()
        {
            ResetProgress();
            if (progressSlider.IsNull()) return;
            progressSlider.gameObject.SetActive(false);
        }

        public void SetProgress(float progress)
        {
            StopReturn();
            if (progressSlider.IsNull()) return;

            progressSlider.value = Mathf.Clamp01(progress);
        }

        public void ResetProgress()
        {
            StopReturn();
            if (progressSlider.IsNull()) return;

            progressSlider.value = 0f;
        }

        public void CancelAndReturnToZero()
        {
            StopReturn();

            if (progressSlider.IsNull()) return;

            returnRoutine = StartCoroutine(ReturnToZeroRoutine());
        }

        public override void BeforeClose()
        {
            base.BeforeClose();
            Hide();
        }

        private void StopReturn()
        {
            if (returnRoutine == null) return;

            StopCoroutine(returnRoutine);
            returnRoutine = null;
        }

        private IEnumerator ReturnToZeroRoutine()
        {
            var startValue = progressSlider.value;
            var elapsed = 0f;

            while (elapsed < cancelReturnDuration)
            {
                elapsed += Timer.UnscaledTime;

                var time = Mathf.Clamp01(elapsed / cancelReturnDuration);
                var easedTime = 1f - Mathf.Pow(1f - time, 3f);

                progressSlider.value = Mathf.Lerp(startValue, 0f, easedTime);

                yield return null;
            }

            progressSlider.value = 0f;
            returnRoutine = null;
        }

        public void UpdateContent(ActionEnvelope focus)
        {
            if (focus.ActivationMode == ActionActivationMode.Instant)
            {
                Hide();
            }
            else
            {
                Show();
            }
        }
    }
}