using System; using System.Collections; using TMPro; using UnityEngine; using UnityEngine.UI; using Core.SaveLoad; using Core; namespace Levels { /// /// UI overlay for confirming a level switch. Displays level info and handles confirm/cancel actions. /// public class LevelSwitchMenu : MonoBehaviour { [Header("UI References")] public Image mainLevelIconImage; public Image minigameIconImage; public TMP_Text mainLevelNameText; public TMP_Text minigameLevelNameText; public Button puzzleLevelConfirmButton; public Button puzzleLevelRestartButton; public Button cancelButton; public Button minigameConfirmButton; public GameObject popupConfirmMenu; public Button popupConfirmButton; public Button popupCancelButton; public Image tintTargetImage; public Color disabledTintColor = new Color(0.5f, 0.5f, 0.5f, 1f); // grey by default [Header("Minigame Lock")] public Image padlockImage; [Header("Scroll View")] public ScrollRect scrollView; public Button scrollToPuzzleLevelButton; public Button scrollToMinigameButton; public float scrollDuration = 1f; private Color _originalTintColor; private Color _originalMinigameIconColor; private Action _onRestart; private Coroutine _activeScrollCoroutine; private Action _onLevelConfirm; private Action _onMinigameConfirm; private Action _onCancel; private LevelSwitchData _switchData; /// /// Initialize the menu with data and callbacks. /// public void Setup(LevelSwitchData switchData, Action onLevelConfirm, Action onMinigameConfirm, Action onCancel, Action onRestart = null) { _switchData = switchData; _onLevelConfirm = onLevelConfirm; _onMinigameConfirm = onMinigameConfirm; _onCancel = onCancel; _onRestart = onRestart; if(switchData != null) { if (mainLevelIconImage) { mainLevelIconImage.sprite = switchData.menuSprite != null ? switchData.menuSprite : switchData.mapSprite; } if (minigameIconImage) { minigameIconImage.sprite = switchData.minigameMenuSprite; } if (mainLevelNameText) mainLevelNameText.text = switchData?.targetLevelSceneName ?? ""; if (minigameLevelNameText) minigameLevelNameText.text = switchData.targetMinigameSceneName ?? ""; } else { Logging.Warning("[LevelSwitchMenu] No level data is assigned!"); } // Setup button listeners if (puzzleLevelConfirmButton) puzzleLevelConfirmButton.onClick.AddListener(OnPuzzleLevelConfirmClicked); if (puzzleLevelRestartButton) puzzleLevelRestartButton.onClick.AddListener(OnRestartClicked); if (cancelButton) cancelButton.onClick.AddListener(OnCancelClicked); if (minigameConfirmButton) minigameConfirmButton.onClick.AddListener(OnMinigameConfirmClicked); if (scrollToPuzzleLevelButton) scrollToPuzzleLevelButton.onClick.AddListener(OnScrollToPuzzleLevelClicked); if (scrollToMinigameButton) scrollToMinigameButton.onClick.AddListener(OnScrollToMinigameClicked); if (popupConfirmButton) popupConfirmButton.onClick.AddListener(OnPopupConfirmClicked); if (popupCancelButton) popupCancelButton.onClick.AddListener(OnPopupCancelClicked); if (popupConfirmMenu) popupConfirmMenu.SetActive(false); if (tintTargetImage) _originalTintColor = tintTargetImage.color; if (minigameIconImage) _originalMinigameIconColor = minigameIconImage.color; // Initialize scroll view to start at left (puzzle level view) if (scrollView) scrollView.horizontalNormalizedPosition = 0f; // Initialize scroll button visibility if (scrollToMinigameButton) scrollToMinigameButton.gameObject.SetActive(true); if (scrollToPuzzleLevelButton) scrollToPuzzleLevelButton.gameObject.SetActive(false); // --- Minigame unlock state logic --- if (SaveLoadManager.Instance != null) { if (SaveLoadManager.Instance.IsSaveDataLoaded) { ApplyMinigameUnlockState(); } else { SaveLoadManager.Instance.OnLoadCompleted += OnSaveDataLoadedHandler; } } } private void OnDestroy() { if (puzzleLevelConfirmButton) puzzleLevelConfirmButton.onClick.RemoveListener(OnPuzzleLevelConfirmClicked); if (puzzleLevelRestartButton) puzzleLevelRestartButton.onClick.RemoveListener(OnRestartClicked); if (cancelButton) cancelButton.onClick.RemoveListener(OnCancelClicked); if (minigameConfirmButton) minigameConfirmButton.onClick.RemoveListener(OnMinigameConfirmClicked); if (scrollToPuzzleLevelButton) scrollToPuzzleLevelButton.onClick.RemoveListener(OnScrollToPuzzleLevelClicked); if (scrollToMinigameButton) scrollToMinigameButton.onClick.RemoveListener(OnScrollToMinigameClicked); if (popupConfirmButton) popupConfirmButton.onClick.RemoveListener(OnPopupConfirmClicked); if (popupCancelButton) popupCancelButton.onClick.RemoveListener(OnPopupCancelClicked); if (_activeScrollCoroutine != null) { StopCoroutine(_activeScrollCoroutine); _activeScrollCoroutine = null; } if (SaveLoadManager.Instance != null) { SaveLoadManager.Instance.OnLoadCompleted -= OnSaveDataLoadedHandler; } } private void OnPuzzleLevelConfirmClicked() { _onLevelConfirm?.Invoke(); Destroy(gameObject); } private void OnMinigameConfirmClicked() { _onMinigameConfirm?.Invoke(); Destroy(gameObject); } private void OnCancelClicked() { _onCancel?.Invoke(); Destroy(gameObject); } private void OnRestartClicked() { if (popupConfirmMenu) popupConfirmMenu.SetActive(true); if (tintTargetImage) tintTargetImage.color = disabledTintColor; } private void OnPopupCancelClicked() { if (popupConfirmMenu) popupConfirmMenu.SetActive(false); if (tintTargetImage) tintTargetImage.color = _originalTintColor; } private void OnPopupConfirmClicked() { _onRestart?.Invoke(); if (popupConfirmMenu) popupConfirmMenu.SetActive(false); if (tintTargetImage) tintTargetImage.color = _originalTintColor; } private void OnScrollToMinigameClicked() { if (_activeScrollCoroutine != null) { StopCoroutine(_activeScrollCoroutine); } _activeScrollCoroutine = StartCoroutine(ScrollToMinigameCoroutine()); } private void OnScrollToPuzzleLevelClicked() { if (_activeScrollCoroutine != null) { StopCoroutine(_activeScrollCoroutine); } _activeScrollCoroutine = StartCoroutine(ScrollToPuzzleLevelCoroutine()); } private IEnumerator ScrollToMinigameCoroutine() { // Hide the scroll to minigame button if (scrollToMinigameButton) scrollToMinigameButton.gameObject.SetActive(false); // Scroll to the right (normalized position 0.95) float elapsed = 0f; float startPos = scrollView.horizontalNormalizedPosition; float targetPos = 0.9f; while (elapsed < scrollDuration) { elapsed += Time.deltaTime; float t = Mathf.Clamp01(elapsed / scrollDuration); // Use SmoothStep for a smoother animation float smoothT = Mathf.SmoothStep(0f, 1f, t); scrollView.horizontalNormalizedPosition = Mathf.Lerp(startPos, targetPos, smoothT); yield return null; } // Ensure we're at the final position scrollView.horizontalNormalizedPosition = targetPos; // Show the scroll to puzzle level button if (scrollToPuzzleLevelButton) scrollToPuzzleLevelButton.gameObject.SetActive(true); _activeScrollCoroutine = null; } private IEnumerator ScrollToPuzzleLevelCoroutine() { // Hide the scroll to puzzle level button if (scrollToPuzzleLevelButton) scrollToPuzzleLevelButton.gameObject.SetActive(false); // Scroll to the left (normalized position 0) float elapsed = 0f; float startPos = scrollView.horizontalNormalizedPosition; float targetPos = 0f; while (elapsed < scrollDuration) { elapsed += Time.deltaTime; float t = Mathf.Clamp01(elapsed / scrollDuration); // Use SmoothStep for a smoother animation float smoothT = Mathf.SmoothStep(0f, 1f, t); scrollView.horizontalNormalizedPosition = Mathf.Lerp(startPos, targetPos, smoothT); yield return null; } // Ensure we're at the final position scrollView.horizontalNormalizedPosition = targetPos; // Show the scroll to minigame button if (scrollToMinigameButton) scrollToMinigameButton.gameObject.SetActive(true); _activeScrollCoroutine = null; } private void ApplyMinigameUnlockState() { if (_switchData == null) return; // Use the new public API to check unlock status string minigameName = _switchData.targetMinigameSceneName; bool unlocked = SaveLoadManager.Instance != null && SaveLoadManager.Instance.IsMinigameUnlocked(minigameName); // Show/hide padlock if (padlockImage) padlockImage.gameObject.SetActive(!unlocked); // Tint minigame icon if locked if (minigameIconImage) { minigameIconImage.color = unlocked ? _originalMinigameIconColor : disabledTintColor; } // Enable/disable minigame confirm button if (minigameConfirmButton) { minigameConfirmButton.interactable = unlocked; } } private void OnSaveDataLoadedHandler(string slot) { ApplyMinigameUnlockState(); if (SaveLoadManager.Instance != null) { SaveLoadManager.Instance.OnLoadCompleted -= OnSaveDataLoadedHandler; } } } }