using Core; using Core.SaveLoad; using UnityEngine; namespace UI.CardSystem.StateMachine.States { /// /// Card is in pending face-down state in corner, awaiting drag. /// On drag start, queries AlbumViewPage for card data and slot, triggers page navigation, /// then flips and transitions to dragging revealed state. /// public class CardPendingFaceDownState : AppleState, ICardStateDragHandler { [Header("State-Owned Visuals")] [SerializeField] private GameObject cardBackVisual; private CardContext _context; private bool _isFlipping; private AlbumCardSlot _targetSlot; private bool _dragEndedDuringFlip = false; // Track if user released before card flip animation completed private void Awake() { _context = GetComponentInParent(); } public override void OnEnterState() { if (_context == null) return; _isFlipping = false; _targetSlot = null; _dragEndedDuringFlip = false; // Reset scale to normal (in case transitioning from scaled state) _context.RootTransform.localScale = Vector3.one; // Show card back, hide card front if (cardBackVisual != null) { cardBackVisual.SetActive(true); cardBackVisual.transform.localRotation = Quaternion.Euler(0, 0, 0); } if (_context.CardDisplay != null) { _context.CardDisplay.gameObject.SetActive(false); _context.CardDisplay.transform.localRotation = Quaternion.Euler(0, 180, 0); } } /// /// Handle drag start - STATE ORCHESTRATES ITS OWN FLOW /// public bool OnCardDragStarted(CardContext context) { if (_isFlipping) return true; // Already handling // Get AlbumViewPage from context (injected dependency) var albumPage = context.AlbumViewPage; if (albumPage == null) { Logging.Warning("[CardPendingFaceDownState] AlbumViewPage not injected!"); return true; } // Step 2: Ask AlbumViewPage what card to display and prompt it to rebuild var cardData = albumPage.GetCardForPendingSlot(); if (cardData == null) { Logging.Warning("[CardPendingFaceDownState] No card data available from AlbumViewPage!"); return true; } // Step 3: Apply card data to context // Use UpdateCardData instead of SetupCard to preserve OriginalScale // (card was already initialized with correct scale in SpawnCardInSlot) context.UpdateCardData(cardData); Logging.Debug($"[CardPendingFaceDownState] Assigned card data: {cardData.Name} ({cardData.Zone})"); // Step 4: Ask AlbumViewPage for target slot _targetSlot = albumPage.GetTargetSlotForCard(cardData); if (_targetSlot == null) { Logging.Warning($"[CardPendingFaceDownState] No slot found for card {cardData.DefinitionId}"); // Still flip and show card, but won't be able to place it } // Step 5: Request page navigation (no callback needed - AlbumViewPage tracks state) albumPage.NavigateToCardPage(cardData, null); // Step 6: Start card flip animation StartFlipAnimation(); return true; // We handled it, prevent default DraggingState transition } /// /// Handle drag end - if card flip animation still in progress, flag it for next state /// public bool OnCardDragEnded(CardContext context) { if (_isFlipping) { // Card flip animation still in progress - user released immediately _dragEndedDuringFlip = true; Logging.Debug("[CardPendingFaceDownState] Drag ended during card flip - will pass to next state"); return true; // We handled it } return false; // Already transitioned to DraggingRevealedState, let it handle } private void StartFlipAnimation() { _isFlipping = true; // Scale up from corner size to normal dragging size if (_context.Animator != null) { _context.Animator.AnimateScale(_context.OriginalScale * 1.15f, 0.3f); } // Play flip animation if (_context.Animator != null) { _context.Animator.PlayFlip( cardBack: cardBackVisual != null ? cardBackVisual.transform : null, cardFront: _context.CardDisplay != null ? _context.CardDisplay.transform : null, onComplete: OnFlipComplete ); } else { // No animator, just switch visibility immediately if (cardBackVisual != null) cardBackVisual.SetActive(false); if (_context.CardDisplay != null) _context.CardDisplay.gameObject.SetActive(true); OnFlipComplete(); } } private void OnFlipComplete() { // Transition to dragging revealed state // Pass target slot to next state (it will query AlbumService for flip status) var card = _context.GetComponent(); if (card != null) { var draggingState = card.GetStateComponent(CardStateNames.DraggingRevealed); if (draggingState != null) { draggingState.SetTargetSlot(_targetSlot); // If drag ended before we transitioned, tell next state to handle placement immediately if (_dragEndedDuringFlip) { draggingState.SetDragAlreadyEnded(true); Logging.Debug("[CardPendingFaceDownState] Passing drag-ended flag to DraggingRevealedState"); } } } _context.StateMachine.ChangeState(CardStateNames.DraggingRevealed); } private void OnDisable() { // Hide card back when leaving state if (cardBackVisual != null) { cardBackVisual.SetActive(false); } } } }