using System.Collections; using System.Collections.Generic; using DG.Tweening; using ShiroginSDK.Runtime.Core.SDK; using ShiroginSDK.Runtime.Core.Utils; using ShiroginSDK.Runtime.Modules.Events; using ShiroginSDK.Runtime.Modules.UI.Popup.Enums; using ShiroginSDK.Runtime.Modules.UI.Popup.Scripts.SO; using ShiroginSDK.Runtime.Modules.UI.Popup.Scripts.UI.Base; using ShiroginSDK.Runtime.Services.Base; using ShiroginSDK.Runtime.Services.Interfaces; using ShiroginSDK.Runtime.Shared.Constants; using UnityEngine; using UnityEngine.UI; namespace ShiroginSDK.Runtime.Services.Implementations.UI { /// /// Manages all queued popups with background dimming and smooth animations. /// Integrated with EventService to automatically respond to common SDK events. /// public class PopupService : ServiceBase, IPopupService { private readonly Queue<(PopupType, object)> _popupQueue = new(); private CanvasGroup _dimBackground; private bool _isShowing; private PopupRepository _repository; private Canvas _rootCanvas; // ---------------------------------------------------- // Initialization // ---------------------------------------------------- public void Initialize(Canvas canvas, PopupRepository repository) { _rootCanvas = canvas; _repository = repository; InitializeDim(); } // ---------------------------------------------------- // Public API // ---------------------------------------------------- public void Show(PopupType type, object data = null) { Enqueue(type, data); } public void SetRepository(PopupRepository repo) { _repository = repo; } public void SetCanvas(Canvas canvas) { _rootCanvas = canvas; } // ---------------------------------------------------- // Lifecycle // ---------------------------------------------------- protected override void OnInitialize() { // Load repository from SDKConfig var config = ShiroginConfig.Load(); if (config == null) { Debug.LogError("[PopupService] ❌ SDKConfig not found! Cannot load PopupRepository."); return; } _repository = config.popupRepository; if (_repository == null) Debug.LogWarning("[PopupService] ⚠️ PopupRepository is null in SDKConfig."); // Try to find root canvas automatically if none assigned if (_rootCanvas == null) _rootCanvas = Object.FindFirstObjectByType(); InitializeDim(); SubscribeToEvents(); Debug.Log("[PopupService] ✅ Initialized and bound to SDKConfig."); } protected override void OnDispose() { _popupQueue.Clear(); _isShowing = false; } // ---------------------------------------------------- // Event Wiring // ---------------------------------------------------- private void SubscribeToEvents() { var eventService = ServiceLocator.Get(); if (eventService == null) { Debug.LogError("[PopupService] ❌ EventService not found."); return; } eventService.Subscribe(e => Enqueue(PopupType.RewardClaimed, e)); eventService.Subscribe(e => Enqueue(PopupType.PurchaseSuccess, e)); eventService.Subscribe(e => Enqueue(PopupType.NoConnection, e)); eventService.Subscribe(e => Enqueue(PopupType.PurchaseFailed, e)); eventService.Subscribe(e => { if (!e.Success) Enqueue(PopupType.NoAdsAvailable, e); }); eventService.Subscribe(e => { Enqueue(PopupType.RewardedAdUnavailable, e); }); eventService.Subscribe(e => Enqueue(PopupType.Shop_UIStoreItem_Rewarded, e)); } private void InitializeDim() { if (_dimBackground != null) return; var dimObj = new GameObject("PopupDimmer", typeof(RectTransform), typeof(CanvasGroup), typeof(Image)); dimObj.transform.SetParent(_rootCanvas ? _rootCanvas.transform : null, false); var img = dimObj.GetComponent(); img.color = new Color(0, 0, 0, 0.6f); _dimBackground = dimObj.GetComponent(); _dimBackground.alpha = 0; _dimBackground.blocksRaycasts = false; dimObj.transform.SetAsFirstSibling(); } private void Enqueue(PopupType type, object data) { _popupQueue.Enqueue((type, data)); if (!_isShowing) CoroutineRunner.Start(ProcessQueue()); } private IEnumerator ProcessQueue() { _isShowing = true; while (_popupQueue.Count > 0) { var (type, data) = _popupQueue.Dequeue(); yield return ShowPopup(type, data); } _isShowing = false; yield return FadeDim(false); } private IEnumerator ShowPopup(PopupType type, object data) { if (_repository == null) { Debug.LogError("[PopupService] ❌ PopupRepository not assigned or missing in SDKConfig!"); yield break; } var prefab = _repository.GetPrefab(type); if (prefab == null) { Debug.LogWarning($"[PopupService] ⚠️ No popup prefab for type: {type}"); yield break; } yield return FadeDim(true); var instance = Object.Instantiate(prefab.gameObject, _rootCanvas ? _rootCanvas.transform : null); var popup = instance.GetComponent(); popup.Initialize(data); yield return popup.AnimateIn(); yield return new WaitUntil(() => popup.IsClosed); yield return popup.AnimateOut(); Object.Destroy(instance); } // ---------------------------------------------------- // Dimmer Control // ---------------------------------------------------- private IEnumerator FadeDim(bool fadeIn) { if (_dimBackground == null) yield break; _dimBackground.blocksRaycasts = fadeIn; DOTween.To(() => _dimBackground.alpha, x => _dimBackground.alpha = x, fadeIn ? 1f : 0f, 0.3f); yield return new WaitForSeconds(UIConstants.FadeDuration); } } }