using System.Collections.Generic; using System.Linq; using CardSystem.UI.Component; using Core; using Minigames.StatueDressup.Controllers; using Minigames.StatueDressup.PhotoGallery; using UnityEngine; using Utils; namespace CardSystem.Controllers { /// /// Controller for managing photo slots across album pages. /// Discovers all AlbumPhotoSlot prefabs in scene, groups by CaptureType, /// and populates with latest photos from PhotoManager. /// public class AlbumPhotoPageController { private readonly GameObject _backdrop; private readonly Transform _enlargedContainer; private readonly float _animationDuration; private Dictionary> _slotsByType; private Dictionary _photoAssignments; // Maps each slot to its assigned photoId private PhotoEnlargeController _enlargeController; private bool _isInitialized; public bool IsInitialized => _isInitialized; /// /// Constructor /// /// Backdrop for photo enlargement /// Container for enlarged photos /// Duration for enlarge/shrink animations public AlbumPhotoPageController(GameObject backdrop, Transform enlargedContainer, float animationDuration = 0.3f) { _backdrop = backdrop; _enlargedContainer = enlargedContainer; _animationDuration = animationDuration; // Initialize data structures _photoAssignments = new Dictionary(); // Initialize enlarge controller _enlargeController = new PhotoEnlargeController(backdrop, enlargedContainer, animationDuration); Logging.Debug("[AlbumPhotoPageController] Controller created"); } /// /// Discover all photo slots in scene and populate them with latest photos /// public void Initialize() { Logging.Debug("[AlbumPhotoPageController] Initialize() called"); if (_isInitialized) { Logging.Warning("[AlbumPhotoPageController] Already initialized"); return; } // Find all photo slots in scene AlbumPhotoSlot[] allSlots = Object.FindObjectsByType(FindObjectsInactive.Include, FindObjectsSortMode.None); Logging.Debug($"[AlbumPhotoPageController] Found {(allSlots != null ? allSlots.Length : 0)} AlbumPhotoSlot components in scene"); if (allSlots == null || allSlots.Length == 0) { Logging.Warning("[AlbumPhotoPageController] No AlbumPhotoSlot components found in scene"); _isInitialized = true; return; } // Group slots by CaptureType _slotsByType = new Dictionary>(); foreach (var slot in allSlots) { Logging.Debug($"[AlbumPhotoPageController] Processing slot: {slot.name}, CaptureType: {slot.CaptureType}"); if (!_slotsByType.ContainsKey(slot.CaptureType)) { _slotsByType[slot.CaptureType] = new List(); } _slotsByType[slot.CaptureType].Add(slot); // Initialize the slot with this controller slot.Initialize(this); } Logging.Debug($"[AlbumPhotoPageController] Found {allSlots.Length} photo slots across {_slotsByType.Count} capture types"); // Log slot counts per type foreach (var kvp in _slotsByType) { Logging.Debug($"[AlbumPhotoPageController] {kvp.Key}: {kvp.Value.Count} slots"); } // Prepare photo assignments (but don't populate yet - slots will request when they become active) Logging.Debug("[AlbumPhotoPageController] Starting PreparePhotoAssignments()"); PreparePhotoAssignments(); _isInitialized = true; Logging.Debug("[AlbumPhotoPageController] Initialize() complete"); } /// /// Prepare photo assignments for all discovered slots. /// Slots will request their assigned photo when they become active. /// private void PreparePhotoAssignments() { _photoAssignments.Clear(); foreach (var kvp in _slotsByType) { CaptureType captureType = kvp.Key; List slots = kvp.Value; // Get latest photos for this capture type int slotCount = slots.Count; List photoIds = PhotoManager.GetPhotoIds(captureType, slotCount); Logging.Debug($"[AlbumPhotoPageController] Preparing assignments for {slotCount} slots of {captureType} with {photoIds.Count} photos"); // Build assignment map for (int i = 0; i < slots.Count; i++) { string photoId = (i < photoIds.Count) ? photoIds[i] : null; _photoAssignments[slots[i]] = photoId; if (photoId != null) { Logging.Debug($"[AlbumPhotoPageController] Slot {i} ({slots[i].name}) -> {photoId}"); } else { Logging.Debug($"[AlbumPhotoPageController] Slot {i} ({slots[i].name}) -> (no photo)"); } } } Logging.Debug($"[AlbumPhotoPageController] Prepared {_photoAssignments.Count} photo assignments"); } /// /// Get the assigned photo ID for a specific slot. /// Called by slots when they become active. /// public string GetAssignedPhotoId(AlbumPhotoSlot slot) { if (slot == null || _photoAssignments == null) { return null; } if (_photoAssignments.TryGetValue(slot, out string photoId)) { return photoId; } Logging.Warning($"[AlbumPhotoPageController] Slot {slot.name} not found in assignments"); return null; } /// /// Refresh photos for a specific capture type (call after new photo is taken) /// public void RefreshPhotosForType(CaptureType captureType) { if (!_isInitialized || !_slotsByType.ContainsKey(captureType)) { return; } List slots = _slotsByType[captureType]; // Clear existing slots foreach (var slot in slots) { slot.Clear(); } // Get latest photos and rebuild assignments int slotCount = slots.Count; List photoIds = PhotoManager.GetPhotoIds(captureType, slotCount); Logging.Debug($"[AlbumPhotoPageController] Refreshing assignments for {slotCount} slots of {captureType} with {photoIds.Count} photos"); // Update assignments for (int i = 0; i < slots.Count; i++) { string photoId = (i < photoIds.Count) ? photoIds[i] : null; _photoAssignments[slots[i]] = photoId; } // Trigger slots to reload (they will request their new assignment when they become active) foreach (var slot in slots) { if (slot.gameObject.activeInHierarchy) { // If slot is currently active, immediately populate with new assignment slot.PopulateWithPhoto(GetAssignedPhotoId(slot)); } } } /// /// Refresh all photo slots (call after album is opened to show latest photos) /// public void RefreshAllPhotos() { if (!_isInitialized) { return; } foreach (var captureType in _slotsByType.Keys.ToList()) { RefreshPhotosForType(captureType); } Logging.Debug("[AlbumPhotoPageController] All photos refreshed"); } /// /// Enlarge a photo (called by AlbumPhotoSlot) /// public void EnlargePhoto(AlbumPhotoSlot slot, Texture2D fullSizeTexture) { if (_enlargeController == null) { Logging.Error("[AlbumPhotoPageController] Enlarge controller not initialized"); return; } // If already enlarged, shrink it if (_enlargeController.IsPhotoEnlarged) { _enlargeController.ShrinkPhoto(); return; } if (fullSizeTexture == null) { Logging.Error($"[AlbumPhotoPageController] Cannot enlarge null texture for slot {slot.PhotoId}"); return; } Logging.Debug($"[AlbumPhotoPageController] Enlarging photo: {slot.PhotoId} from {slot.CaptureType}"); // Default enlarged scale (can be made configurable) float enlargedScale = 2.5f; // Enlarge using the controller _enlargeController.EnlargePhoto(slot, slot.gameObject, fullSizeTexture, enlargedScale); } /// /// Get photo count for a specific capture type /// public int GetPhotoCount(CaptureType captureType) { return PhotoManager.GetPhotoCount(captureType); } /// /// Get slot count for a specific capture type /// public int GetSlotCount(CaptureType captureType) { if (!_isInitialized || !_slotsByType.ContainsKey(captureType)) { return 0; } return _slotsByType[captureType].Count; } /// /// Cleanup when album is closed /// public void Cleanup() { if (_enlargeController != null) { _enlargeController.Cleanup(); } // Clear all slots if (_slotsByType != null) { foreach (var slots in _slotsByType.Values) { foreach (var slot in slots) { if (slot != null) { slot.Clear(); } } } } Logging.Debug("[AlbumPhotoPageController] Cleanup complete"); } } }