using System.Collections.Generic; using AppleHills.Data.CardSystem; using Core; using UnityEngine; namespace UI.CardSystem { /// /// Manages album page navigation, zone mapping, and page flip tracking. /// Created and owned by AlbumViewPage (not a Unity component). /// public class AlbumNavigationService { private readonly BookCurlPro.BookPro _book; private readonly BookTabButton[] _zoneTabs; private bool _isPageFlipping = false; /// /// Is the book currently flipping to a page? /// public bool IsPageFlipping => _isPageFlipping; /// /// Constructor - called by AlbumViewPage's lazy property /// public AlbumNavigationService(BookCurlPro.BookPro book, BookTabButton[] zoneTabs) { _book = book; _zoneTabs = zoneTabs; } /// /// Check if we're currently viewing the album proper (not the menu page) /// public bool IsInAlbumProper() { if (_book == null) { Logging.Warning("[AlbumNavigationService] Book reference is null"); return false; } // Page 1 is the menu/cover, page 2+ are album pages with card slots return _book.CurrentPaper > 1; } /// /// Navigate to the page where a specific card belongs /// public void NavigateToCardPage(CardData cardData, System.Action onComplete) { if (cardData == null || _book == null) { onComplete?.Invoke(); return; } // Find target page based on card's zone int targetPage = FindPageForZone(cardData.Zone); if (targetPage < 0) { Logging.Warning($"[AlbumNavigationService] No page found for zone {cardData.Zone}"); onComplete?.Invoke(); return; } // Mark as flipping _isPageFlipping = true; Logging.Debug($"[AlbumNavigationService] Starting page flip to page {targetPage}"); // Get or add AutoFlip component BookCurlPro.AutoFlip autoFlip = _book.GetComponent(); if (autoFlip == null) { autoFlip = _book.gameObject.AddComponent(); } // Start flipping with callback autoFlip.enabled = true; autoFlip.StartFlipping(targetPage, () => { // Mark as complete _isPageFlipping = false; Logging.Debug($"[AlbumNavigationService] Page flip to {targetPage} completed"); // Call original callback if provided onComplete?.Invoke(); }); } /// /// Get list of card definition IDs on the current page /// public List GetDefinitionsOnCurrentPage() { var result = new List(); if (_book == null) return result; int currentPage = _book.CurrentPaper; // Find all AlbumCardSlot in scene var allSlots = Object.FindObjectsByType(FindObjectsSortMode.None); foreach (var slot in allSlots) { if (IsSlotOnPage(slot.transform, currentPage)) { if (slot.TargetCardDefinition != null && !string.IsNullOrEmpty(slot.TargetCardDefinition.Id)) { result.Add(slot.TargetCardDefinition.Id); } } } return result; } #region Private Helpers /// /// Find the target page for a card zone using BookTabButtons /// private int FindPageForZone(CardZone zone) { if (_zoneTabs == null || _zoneTabs.Length == 0) { Logging.Warning("[AlbumNavigationService] No zone tabs available!"); return -1; } foreach (var tab in _zoneTabs) { if (tab.Zone == zone) { return tab.TargetPage; } } Logging.Warning($"[AlbumNavigationService] No BookTabButton found for zone {zone}"); return -1; } /// /// Check if a slot's transform is on a specific book page /// private bool IsSlotOnPage(Transform slotTransform, int pageIndex) { if (_book == null || _book.papers == null || pageIndex < 0 || pageIndex >= _book.papers.Length) return false; var paper = _book.papers[pageIndex]; if (paper == null) return false; // Check if slotTransform parent hierarchy contains paper.Front or paper.Back Transform current = slotTransform; while (current != null) { if ((paper.Front != null && current.gameObject == paper.Front) || (paper.Back != null && current.gameObject == paper.Back)) return true; current = current.parent; } return false; } #endregion } }