using Cysharp.Threading.Tasks;
using System; // System.Type 사용을 위해 추가
using System.Threading;
using UnityEngine;
using UnityEngine.UI;
using UVC.Log;
namespace UVC.UI.Modal
{
///
/// ✨짠! 특별한 알림 상자를 보여주는 마법사, Modal 클래스예요! ✨
/// 게임을 하다가 갑자기 "레벨 업!" 메시지가 뜨거나, "정말 게임을 끌 건가요?" 하고 물어보는 창 있죠?
/// 그런 창들을 '모달'이라고 불러요. Modal 클래스는 이런 모달 창을 쉽게 만들고 보여줄 수 있게 도와준답니다.
/// 마치 요술봉처럼, 필요할 때 "모달 나와라, 뚝딱!" 하고 명령하면 화면에 알림 상자를 뿅! 하고 나타나게 할 수 있어요.
/// 그리고 다 봤으면 "모달 들어가라, 뿅!" 하고 사라지게 할 수도 있죠.
///
public static class Modal
{
///
/// 📦 현재 열려있는 모달의 내용물(ModalContent)을 가리키는 포인터예요.
/// 모달이 열릴 때 설정되고, 닫힐 때 null이 됩니다.
/// OnClose 호출 시 사용됩니다.
///
private static ModalContent currentContent;
///
/// 🧙♂️ 현재 화면에 떠 있는 모달 창 자체를 가리키는 비밀 포인터예요.
/// 모달이 열리면 여기에 그 모달 창이 저장되고, 닫히면 null(없음)이 돼요.
/// 한 번에 하나의 모달만 보여주기 위해 이 포인터를 사용해요.
///
private static GameObject currentModalInstance;
///
/// 🛡️ 모달 창이 뜰 때 뒤에 있는 다른 버튼들을 누르지 못하게 막아주는 '투명 방패'예요.
/// 이 방패도 모달이 열릴 때 나타났다가, 닫히면 사라져요.
///
private static GameObject currentBlockerInstance;
///
/// 📜 모달 창이 "네!" 또는 "아니오!" 같은 대답을 받을 때까지 기다리는 '약속 증서'예요.
/// UniTaskCompletionSource의 줄임말인 tcs는 'Task Completion Source'의 약자랍니다.
/// 모달이 열릴 때 이 약속 증서가 만들어지고, 사용자가 버튼을 누르면 여기에 결과가 적혀요.
///
private static IUniTaskSource activeTcs;
///
/// 🏷️ 모달이 돌려줄 대답의 종류(타입)를 기억하는 '이름표'예요.
/// 예를 들어, '예/아니오' 질문이면 bool 타입(참/거짓)이라는 이름표가 붙어요.
///
private static Type activeResultType;
///
/// 🖼️ 모달 뒤에 깔릴 기본 '투명 방패' 디자인 파일이 어디 있는지 알려주는 '주소'예요.
/// 특별히 다른 방패를 쓰고 싶다고 말하지 않으면 이 기본 방패를 사용해요.
///
private const string DefaultBlockerPrefabPath = "Prefabs/UI/Modal/ModalBlocker";
///
/// ✨ 모달아, 열려라! ✨
/// 이 마법 주문을 외치면 화면에 새로운 알림 상자(모달)가 뿅! 하고 나타나요.
/// 어떤 내용을 보여줄지, 버튼은 어떻게 할지 미리 정해서 알려줘야 해요.
///
/// 예를 들어, "정말 게임을 종료할까요?" 라는 질문과 함께 [예], [아니오] 버튼이 있는 모달을 보여주고 싶다고 해봐요.
/// 이럴 때 이 Open 마법을 사용하면 된답니다!
///
/// 모달이 닫힐 때 어떤 대답을 했는지 (예: '예' 버튼을 눌렀는지, '아니오' 버튼을 눌렀는지) 알려줄 수도 있어요.
/// 그 대답의 종류를 여기에 적어주면 돼요. 예를 들어, bool이라고 적으면 '참' 또는 '거짓'으로 대답을 받을 수 있어요.
///
/// 모달이 닫힐 때 돌려받을 대답의 종류예요. 예를 들어, '예'/'아니오' 선택은 bool 타입으로 받을 수 있어요.
/// 모달에 보여줄 제목, 메시지, 버튼 모양 등을 정한 '모달 내용물 꾸러미'예요.
/// 모달이 뜰 때 뒤에 있는 화면을 살짝 가려주는 '가림막'의 디자인 파일 경로예요. 안 써주면 기본 가림막을 사용해요.
/// 모달이 닫힐 때 사용자가 선택한 결과(대답)를 돌려줘요. 예를 들어, '예' 버튼을 누르면 true를 돌려줄 수 있어요.
///
///
/// // "정말 게임을 종료할까요?" 모달을 열고, 사용자의 대답(true 또는 false)을 기다리는 예시예요.
/// async UniTaskVoid ShowExitConfirmModal()
/// {
/// // 1. 모달에 어떤 내용을 보여줄지 정해요.
/// // "MyConfirmModalPrefab" 부분에는 실제 만들어둔 모달 프리팹 파일의 경로를 적어주세요.
/// var myModalContent = new ModalContent("Prefabs/UI/MyConfirmModalPrefab")
/// {
/// Title = "게임 종료",
/// Message = "정말로 게임을 종료하시겠어요? 🥺",
/// ConfirmButtonText = "네! 끌래요",
/// CancelButtonText = "아니요! 더 할래요"
/// };
///
/// // 2. Modal.Open 마법으로 모달을 열어요! 사용자가 버튼을 누를 때까지 기다렸다가, 그 결과를 알려줘요.
/// // 여기서는 사용자가 '네! 끌래요'를 누르면 true, '아니요! 더 할래요'나 닫기 버튼을 누르면 false를 돌려받기로 약속했어요().
/// bool userSaidYes = await Modal.Open(myModalContent);
///
/// // 3. 사용자의 대답에 따라 다른 행동을 해요.
/// if (userSaidYes)
/// {
/// Debug.Log("흑흑, 게임을 종료합니다... 다음에 또 만나요! 👋");
/// // Application.Quit(); // 진짜로 게임을 끄는 코드
/// }
/// else
/// {
/// Debug.Log("야호! 게임을 계속합니다! 🥳");
/// }
/// }
///
///
public static async UniTask Open(ModalContent content, string blockerPrefabPath = DefaultBlockerPrefabPath)
{
// 📜 이야기: 모달을 열기 전에, 이미 다른 모달이 열려있는지 확인해요.
// 만약 그렇다면, "앗! 이미 다른 모달이 열려있어요!"라고 알려주고 새 모달은 열지 않아요.
// 한 번에 하나의 모달만 보여주는 것이 규칙이거든요!
if (currentModalInstance != null)
{
ULog.Warning("[Modal] 다른 모달이 이미 열려있습니다. 새 모달을 열기 전에 기존 모달을 닫아주세요.");
return default(T); // 기본값(예: bool이면 false, 숫자면 0)을 돌려주고 끝내요.
}
// 📜 이야기: 새 모달을 위한 '약속 증서(tcs)'를 만들어요.
// 이 증서는 나중에 사용자가 버튼을 누르면 그 결과를 기록할 거예요.
// 그리고 이 증서와 결과 타입을 마법사의 비밀 도구함에 잘 보관해요.
var tcs = new UniTaskCompletionSource();
activeTcs = tcs;
activeResultType = typeof(T);
currentContent = content; // 현재 content 저장
// --- 투명 방패(Blocker) 준비 ---
CanvasGroup blockerCanvasGroup = null;
// 📜 이야기: '투명 방패' 디자인 파일을 불러와요. Resources.LoadAsync는 비동기(기다리지 않고 다음 일 하기)로 파일을 불러오는 마법이에요.
GameObject blockerPrefabObj = await Resources.LoadAsync(blockerPrefabPath) as GameObject;
if (blockerPrefabObj != null)
{
// 화면에서 가장 큰 그림판(Canvas)을 찾아서 그 위에 방패를 놓을 거예요.
Canvas mainCanvasForBlocker = UnityEngine.Object.FindFirstObjectByType