using AppleHills.Data.CardSystem; using Core; using Core.SaveLoad; using UI.DragAndDrop.Core; using UnityEngine; namespace UI.CardSystem.StateMachine { // ...existing code... public class Card : DraggableObject { [Header("Components")] [SerializeField] private CardContext context; [SerializeField] private CardAnimator animator; [SerializeField] private AppleMachine stateMachine; [Header("Configuration")] [SerializeField] private string initialState = "IdleState"; // Public accessors public CardContext Context => context; public CardAnimator Animator => animator; public AppleMachine StateMachine => stateMachine; public CardData CardData => context?.CardData; // State inspection properties for booster flow public bool IsIdle => GetCurrentStateName() == "IdleState"; public bool IsRevealing => !IsIdle && !IsComplete; public bool IsComplete => context?.HasCompletedReveal ?? false; // Event fired when this card is successfully placed into an AlbumCardSlot public event System.Action OnPlacedInAlbumSlot; protected override void Initialize() { base.Initialize(); // Call DraggableObject initialization // Auto-find components if not assigned if (context == null) context = GetComponent(); if (animator == null) animator = GetComponent(); if (stateMachine == null) stateMachine = GetComponentInChildren(); } #region DraggableObject Hooks - Trigger State Transitions protected override void OnDragStartedHook() { base.OnDragStartedHook(); // Always emit the generic drag started event for external consumers (AlbumViewPage, etc.) context?.NotifyDragStarted(); // Check if current state wants to handle drag behavior if (stateMachine?.currentState != null) { var dragHandler = stateMachine.currentState.GetComponent(); if (dragHandler != null && dragHandler.OnCardDragStarted(context)) { return; // State handled it, don't do default behavior } } // Default behavior: transition to DraggingState // Logging.Debug($"[Card] Drag started on {CardData?.Name}, transitioning to DraggingState"); // ChangeState("DraggingState"); } protected override void OnDragEndedHook() { base.OnDragEndedHook(); // Always emit the generic drag ended event for external consumers context?.NotifyDragEnded(); // Check if current state wants to handle drag end if (stateMachine?.currentState != null) { var dragHandler = stateMachine.currentState.GetComponent(); if (dragHandler != null && dragHandler.OnCardDragEnded(context)) { return; // State handled it } } // Default behavior for states that don't implement custom drag end string current = GetCurrentStateName(); if (current == "DraggingState") { if (CurrentSlot is AlbumCardSlot albumSlot) { Logging.Debug($"[Card] Dropped in album slot, transitioning to PlacedInSlotState"); var placedState = GetStateComponent("PlacedInSlotState"); if (placedState != null) { placedState.SetParentSlot(albumSlot); } ChangeState("PlacedInSlotState"); OnPlacedInAlbumSlot?.Invoke(this, albumSlot); } else { Logging.Debug("[Card] Dropped outside valid slot, returning to RevealedState"); ChangeState("RevealedState"); } } } #endregion /// /// Setup the card with data and optional initial state /// public void SetupCard(CardData data, string startState = null) { if (context != null) { context.SetupCard(data); } // Start the state machine with specified or default state string targetState = startState ?? initialState; if (stateMachine != null && !string.IsNullOrEmpty(targetState)) { stateMachine.ChangeState(targetState); } } /// /// Setup for booster reveal flow (starts at IdleState, will flip on click) /// Dragging is DISABLED for booster cards /// States will query CardSystemManager for collection state as needed /// public void SetupForBoosterReveal(CardData data, bool isNew) { SetupCard(data, "IdleState"); SetDraggingEnabled(false); // Booster cards cannot be dragged } /// /// Setup for album placement (starts at PlacedInSlotState) /// Dragging is DISABLED once placed in slot /// public void SetupForAlbumSlot(CardData data, AlbumCardSlot slot) { SetupCard(data, "PlacedInSlotState"); SetDraggingEnabled(false); // Cards in slots cannot be dragged out // Set the parent slot on the PlacedInSlotState var placedState = GetStateComponent("PlacedInSlotState"); if (placedState != null) { placedState.SetParentSlot(slot); } } /// /// Setup for album pending state (starts at PendingFaceDownState) /// Dragging is ENABLED; state will assign data when dragged /// public void SetupForAlbumPending() { // Start with no data; state will assign when dragged SetupCard(null, "PendingFaceDownState"); SetDraggingEnabled(true); } /// /// Transition to a specific state /// public void ChangeState(string stateName) { if (stateMachine != null) { stateMachine.ChangeState(stateName); } } /// /// Get a specific state component by name /// public T GetStateComponent(string stateName) where T : AppleState { if (stateMachine == null) return null; Transform stateTransform = stateMachine.transform.Find(stateName); if (stateTransform != null) { return stateTransform.GetComponent(); } return null; } /// /// Get the current active state name /// public string GetCurrentStateName() { if (stateMachine?.currentState != null) { return stateMachine.currentState.name; } return "None"; } } }