using System.Collections.Generic; using AppleHills.Data.CardSystem; using Core; using Core.Lifecycle; using Input; using TMPro; using UnityEngine; using UnityEngine.UI; using UI.CardSystem.StateMachine; using UI.CardSystem.StateMachine.States; namespace UI.CardSystem.Testing { /// /// Test controller for card state machine testing. /// Provides UI controls to manually test state transitions, animations, and flows. /// public class CardTestController : ManagedBehaviour { [Header("Test Card")] [SerializeField] private Card testCard; [SerializeField] private CardData testCardData; [Header("UI References")] [SerializeField] private TextMeshProUGUI eventLogText; [SerializeField] private Toggle isNewToggle; [SerializeField] private Slider repeatCountSlider; [SerializeField] private TextMeshProUGUI repeatCountLabel; [SerializeField] private TMP_Dropdown rarityDropdown; [SerializeField] private Toggle isClickableToggle; [SerializeField] private TextMeshProUGUI currentStateText; private List _eventLog = new List(); private CardContext _cardContext; private Vector3 _originalCardPosition; private Vector3 _originalCardScale; private Vector2 _originalAnchoredPosition; private void Awake() { if (testCard != null) { _cardContext = testCard.GetComponent(); _originalCardPosition = testCard.transform.position; _originalCardScale = testCard.transform.localScale; // Store original anchored position if it's a RectTransform RectTransform rectTransform = testCard.GetComponent(); if (rectTransform != null) { _originalAnchoredPosition = rectTransform.anchoredPosition; } // Subscribe to card events (new simplified event model) if (_cardContext != null) { // TODO: FIX // _cardContext.OnRevealFlowComplete += OnCardRevealFlowComplete; } // Subscribe to drag events to ensure card snaps back when released testCard.OnDragStarted += OnCardDragStarted; testCard.OnDragEnded += OnCardDragEnded; } // Setup UI listeners if (repeatCountSlider != null) { repeatCountSlider.onValueChanged.AddListener(OnRepeatCountChanged); } if (isClickableToggle != null) { isClickableToggle.onValueChanged.AddListener(OnIsClickableToggled); } } internal override void OnManagedAwake() { base.OnManagedAwake(); InputManager.Instance.SetInputMode(InputMode.UI); } private void Start() { // Initialize card with test data if (testCard != null && testCardData != null && _cardContext != null) { _cardContext.SetupCard(testCardData); } LogEvent("Card Test Scene Initialized"); UpdateCurrentStateDisplay(); } private void Update() { // Update current state display every frame if (Time.frameCount % 30 == 0) // Every 0.5 seconds at 60fps { UpdateCurrentStateDisplay(); } } #region State Transition Buttons /// /// Reset card to default state (position, scale) before transitioning to a new state. /// This prevents accumulation of tweens and ensures animations play correctly. /// private void ResetCardToDefault() { if (testCard == null || _cardContext == null) return; // Stop all animations if (_cardContext.Animator != null) { _cardContext.Animator.StopAllAnimations(); } // Reset transform immediately testCard.transform.localScale = _originalCardScale; testCard.transform.position = _originalCardPosition; // Reset anchored position if it's a RectTransform RectTransform rectTransform = testCard.GetComponent(); if (rectTransform != null) { rectTransform.anchoredPosition = _originalAnchoredPosition; } LogEvent("Card reset to default state"); } public void TransitionToIdleState() { ResetCardToDefault(); _cardContext?.StateMachine.ChangeState("IdleState"); LogEvent("Transitioned to IdleState"); } public void TransitionToRevealedState() { ResetCardToDefault(); _cardContext?.StateMachine.ChangeState("RevealedState"); LogEvent("Transitioned to RevealedState"); } public void TransitionToEnlargedNewState() { ResetCardToDefault(); _cardContext?.StateMachine.ChangeState("EnlargedNewState"); LogEvent("Transitioned to EnlargedNewState"); } public void TransitionToEnlargedRepeatState() { ResetCardToDefault(); _cardContext?.StateMachine.ChangeState("EnlargedRepeatState"); LogEvent("Transitioned to EnlargedRepeatState"); } public void TransitionToDraggingState() { ResetCardToDefault(); _cardContext?.StateMachine.ChangeState("DraggingState"); LogEvent("Transitioned to DraggingState"); } public void TransitionToAlbumEnlargedState() { ResetCardToDefault(); _cardContext?.StateMachine.ChangeState("AlbumEnlargedState"); LogEvent("Transitioned to AlbumEnlargedState"); } #endregion #region Simulation Buttons public void SimulateNewCardFlow() { if (_cardContext == null) return; // NOTE: These properties no longer exist in CardContext (removed to prevent stale data) // States now query CardSystemManager directly // This test controller manually manipulates state machine for testing only _cardContext.IsClickable = true; TransitionToIdleState(); LogEvent("Simulating NEW CARD flow - click card to flip (test bypasses collection checks)"); } public void SimulateRepeatCardFlow() { if (_cardContext == null) return; // NOTE: RepeatCardCount removed from CardContext // Test directly transitions to state for visual testing _cardContext.IsClickable = true; TransitionToIdleState(); LogEvent($"Simulating REPEAT CARD flow (test bypasses collection checks)"); } public void SimulateUpgradeFlow() { if (_cardContext == null) return; // NOTE: WillTriggerUpgrade removed from CardContext // Test directly transitions to state for visual testing _cardContext.IsClickable = true; TransitionToIdleState(); LogEvent("Simulating UPGRADE flow (test bypasses collection checks)"); } public void TestDragAndSnap() { if (testCard == null) return; // Enable dragging for the test testCard.SetDraggingEnabled(true); TransitionToRevealedState(); LogEvent("DRAG TEST enabled - drag the card and release to see it snap back"); } #endregion #region Card Setup Controls public void ApplyCardSetup() { if (_cardContext == null) return; bool isNew = isNewToggle != null && isNewToggle.isOn; int repeatCount = repeatCountSlider != null ? Mathf.RoundToInt(repeatCountSlider.value) : 0; // Apply rarity if needed if (rarityDropdown != null && testCardData != null) { testCardData.Rarity = (CardRarity)rarityDropdown.value; } LogEvent($"Card setup applied: IsNew={isNew}, RepeatCount={repeatCount}"); } private void OnRepeatCountChanged(float value) { if (repeatCountLabel != null) { repeatCountLabel.text = $"{Mathf.RoundToInt(value)}/5"; } } private void OnIsClickableToggled(bool isClickable) { if (_cardContext != null) { _cardContext.IsClickable = isClickable; LogEvent($"Card clickable: {isClickable}"); } } #endregion #region Animation Test Buttons public void PlayFlipAnimation() { // Reset card first to prevent accumulation ResetCardToDefault(); // Transition to IdleState and programmatically trigger flip TransitionToIdleState(); // Get IdleState and trigger click var idleState = testCard.GetComponentInChildren(); if (idleState != null) { idleState.OnPointerClick(null); LogEvent("Playing flip animation"); } } public void PlayEnlargeAnimation() { if (_cardContext?.Animator != null) { ResetCardToDefault(); _cardContext.Animator.PlayEnlarge(1.5f); LogEvent("Playing enlarge animation"); } } public void PlayShrinkAnimation() { if (_cardContext?.Animator != null) { // Don't reset for shrink - we want to shrink from current state _cardContext.Animator.PlayShrink(Vector3.one, null); LogEvent("Playing shrink animation"); } } public void StartIdleHoverAnimation() { if (_cardContext?.Animator != null) { // Reset card position first to prevent accumulation ResetCardToDefault(); _cardContext.Animator.StartIdleHover(10f, 1.5f, restartIfActive: true); LogEvent("Started idle hover animation"); } } public void StopIdleHoverAnimation() { if (_cardContext?.Animator != null) { _cardContext.Animator.StopIdleHover(_originalAnchoredPosition); LogEvent("Stopped idle hover animation"); } } #endregion #region Utility Buttons public void ResetCardPosition() { if (testCard != null) { testCard.transform.position = _originalCardPosition; testCard.transform.localScale = _originalCardScale; // Reset anchored position if it's a RectTransform RectTransform rectTransform = testCard.GetComponent(); if (rectTransform != null) { rectTransform.anchoredPosition = _originalAnchoredPosition; } LogEvent("Card position reset"); } } public void ClearEventLog() { _eventLog.Clear(); UpdateEventLog(); LogEvent("Event log cleared"); } #endregion #region Event Handlers private void OnCardRevealFlowComplete(CardContext context) { LogEvent($"Event: OnRevealFlowComplete - Card reveal complete for {context.CardData?.Name}"); } private void OnCardDragStarted(UI.DragAndDrop.Core.DraggableObject draggable) { LogEvent("Event: OnDragStarted - Card is being dragged"); } private void OnCardDragEnded(UI.DragAndDrop.Core.DraggableObject draggable) { LogEvent("Event: OnDragEnded - Snapping card back to spawn point"); // Snap card back to original position (no slotting in test scene) if (testCard != null) { testCard.transform.position = _originalCardPosition; // Return to idle state after drag TransitionToIdleState(); } } #endregion #region Event Log private void LogEvent(string message) { string timestamp = $"[{Time.time:F2}s]"; _eventLog.Add($"{timestamp} {message}"); // Keep only last 20 events if (_eventLog.Count > 20) { _eventLog.RemoveAt(0); } UpdateEventLog(); Logging.Debug($"[CardTest] {message}"); } private void UpdateEventLog() { if (eventLogText != null) { eventLogText.text = string.Join("\n", _eventLog); } } private void UpdateCurrentStateDisplay() { if (currentStateText != null && _cardContext != null && _cardContext.StateMachine != null) { // Get the active state by checking which child state GameObject is active string stateName = "Unknown"; Transform stateMachineTransform = _cardContext.StateMachine.transform; for (int i = 0; i < stateMachineTransform.childCount; i++) { Transform child = stateMachineTransform.GetChild(i); if (child.gameObject.activeSelf) { stateName = child.name; break; } } currentStateText.text = $"Current State: {stateName}"; } } #endregion private void OnDestroy() { // Unsubscribe from events if (_cardContext != null) { // TODO: FIX // _cardContext.OnRevealFlowComplete -= OnCardRevealFlowComplete; } if (testCard != null) { testCard.OnDragStarted -= OnCardDragStarted; testCard.OnDragEnded -= OnCardDragEnded; } } } }