using System;
using AppleHills.Data.CardSystem;
using Core;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace UI.CardSystem
{
///
/// Displays a single card using the new visual system with frames, overlays, backgrounds, and zone shapes.
///
public class CardDisplay : MonoBehaviour, IPointerClickHandler
{
[Header("UI Elements")]
[SerializeField] private TextMeshProUGUI cardNameText;
[SerializeField] private Image cardImage;
[SerializeField] private Image frameImage;
[SerializeField] private Image overlayImage;
[SerializeField] private Image backgroundImage;
[SerializeField] private Image zoneShapeImage;
[Header("Card Data")]
[SerializeField] private CardData cardData;
[Header("Visual Settings")]
[SerializeField] private CardVisualConfig visualConfig;
#if UNITY_EDITOR
[Header("Editor Tools")]
[SerializeField] private CardDefinition editorCardDefinition;
#endif
// Events
public event Action OnCardClicked;
// Preview mode tracking for click forwarding
private bool _isPreviewMode;
private AlbumCardSlot _previewSlot;
///
/// Sets up the card display with the given card data
///
public void SetupCard(CardData data)
{
if (data == null)
{
Logging.Warning("[CardDisplay] Attempted to setup card with null data");
return;
}
cardData = data;
UpdateCardVisuals();
}
///
/// Updates all visual elements based on current card data
///
private void UpdateCardVisuals()
{
if (cardData == null)
{
ClearCard();
return;
}
if (visualConfig == null)
{
Logging.Warning("[CardDisplay] No CardVisualConfig assigned. Visuals may not display correctly.");
}
// Update text
UpdateCardName();
// Update main card image
UpdateCardImage();
// Update rarity-based visuals (frame and overlay)
UpdateRarityVisuals();
// Update zone-based visuals (background and shape)
UpdateZoneVisuals();
Logging.Debug($"[CardDisplay] Updated visuals for card: {cardData.Name} (Rarity: {cardData.Rarity}, Zone: {cardData.Zone})");
}
///
/// Apply preview visuals - black tint to card image and question marks for name
/// Used for empty slot previews to show locked/unknown cards
///
public void SetPreviewVisuals()
{
// Set card name to question marks
if (cardNameText != null)
{
cardNameText.text = "??????";
}
// Apply black non-opaque tint to card image
if (cardImage != null)
{
cardImage.color = Color.black;
}
Logging.Debug($"[CardDisplay] Applied preview visuals (black tint and ?????? name)");
}
///
/// Reset preview visuals back to normal
///
public void ClearPreviewVisuals()
{
// Restore normal card name
if (cardData != null && cardNameText != null)
{
cardNameText.text = cardData.Name ?? "Unknown Card";
}
// Reset card image color to white (normal)
if (cardImage != null)
{
cardImage.color = Color.white;
}
Logging.Debug($"[CardDisplay] Cleared preview visuals");
}
///
/// Updates the card name text
///
private void UpdateCardName()
{
if (cardNameText != null)
{
cardNameText.text = cardData.Name ?? "Unknown Card";
}
}
///
/// Updates the main card image
///
private void UpdateCardImage()
{
if (cardImage != null)
{
if (cardData.CardImage != null)
{
cardImage.sprite = cardData.CardImage;
cardImage.enabled = true;
}
else
{
cardImage.sprite = null;
cardImage.enabled = false;
}
}
}
///
/// Updates frame and overlay based on card rarity
///
private void UpdateRarityVisuals()
{
if (visualConfig == null) return;
// Update frame
if (frameImage != null)
{
Sprite frameSprite = visualConfig.GetRarityFrame(cardData.Rarity);
if (frameSprite != null)
{
frameImage.sprite = frameSprite;
frameImage.enabled = true;
}
else
{
frameImage.enabled = false;
}
}
// Update overlay (can be null for some rarities)
if (overlayImage != null)
{
Sprite overlaySprite = visualConfig.GetRarityOverlay(cardData.Rarity);
if (overlaySprite != null)
{
overlayImage.sprite = overlaySprite;
overlayImage.enabled = true;
}
else
{
overlayImage.enabled = false;
}
}
}
///
/// Updates background and zone shape based on card zone and rarity
/// Special handling for Legendary cards
///
private void UpdateZoneVisuals()
{
if (visualConfig == null) return;
// Update background
// Legendary cards get special background, others get zone background
if (backgroundImage != null)
{
Sprite bgSprite = visualConfig.GetBackground(cardData.Zone, cardData.Rarity);
if (bgSprite != null)
{
backgroundImage.sprite = bgSprite;
backgroundImage.enabled = true;
}
else
{
backgroundImage.enabled = false;
}
}
// Update zone shape
// Legendary cards don't show shapes
if (zoneShapeImage != null)
{
Sprite shapeSprite = visualConfig.GetZoneShape(cardData.Zone, cardData.Rarity);
if (shapeSprite != null)
{
zoneShapeImage.sprite = shapeSprite;
zoneShapeImage.enabled = true;
}
else
{
zoneShapeImage.enabled = false;
}
}
}
///
/// Clears all visual elements
///
private void ClearCard()
{
if (cardNameText != null) cardNameText.text = "";
if (cardImage != null) cardImage.enabled = false;
if (frameImage != null) frameImage.enabled = false;
if (overlayImage != null) overlayImage.enabled = false;
if (backgroundImage != null) backgroundImage.enabled = false;
if (zoneShapeImage != null) zoneShapeImage.enabled = false;
}
///
/// Called when the card is clicked
///
public void OnClick()
{
OnCardClicked?.Invoke(this);
}
///
/// Returns the card data associated with this display
///
public CardData GetCardData()
{
return cardData;
}
///
/// Updates the visual config reference
///
public void SetVisualConfig(CardVisualConfig config)
{
visualConfig = config;
if (cardData != null)
{
UpdateCardVisuals();
}
}
///
/// Enable preview mode - when clicked, forwards click to the associated slot
///
public void SetPreviewMode(bool isEnabled, AlbumCardSlot slot = null)
{
_isPreviewMode = isEnabled;
_previewSlot = slot;
// Enable raycast targets on images so this CardDisplay can receive clicks
if (cardImage != null) cardImage.raycastTarget = isEnabled;
if (frameImage != null) frameImage.raycastTarget = isEnabled;
if (overlayImage != null) overlayImage.raycastTarget = isEnabled;
if (backgroundImage != null) backgroundImage.raycastTarget = isEnabled;
if (zoneShapeImage != null) zoneShapeImage.raycastTarget = isEnabled;
Logging.Debug($"[CardDisplay] Preview mode {(isEnabled ? "enabled" : "disabled")}, slot: {(slot != null ? slot.name : "NULL")}");
}
///
/// Handle click on CardDisplay - forward to preview slot if in preview mode
///
public void OnPointerClick(PointerEventData eventData)
{
Logging.Debug($"[CLICK-TRACE-CARDDISPLAY] OnPointerClick on {name}, _isPreviewMode={_isPreviewMode}, _previewSlot={((_previewSlot != null) ? _previewSlot.name : "NULL")}");
if (_isPreviewMode && _previewSlot != null)
{
Logging.Debug($"[CLICK-TRACE-CARDDISPLAY] {name} - In preview mode, calling DismissPreview on slot: {_previewSlot.name}");
_previewSlot.DismissPreview();
}
else
{
// Not in preview mode - forward click to parent AlbumCard (if it exists)
AlbumCard parentAlbumCard = GetComponentInParent();
if (parentAlbumCard != null)
{
Logging.Debug($"[CLICK-TRACE-CARDDISPLAY] {name} - Forwarding click to parent AlbumCard");
parentAlbumCard.OnPointerClick(eventData);
}
else
{
Logging.Debug($"[CLICK-TRACE-CARDDISPLAY] {name} - No parent AlbumCard, firing OnCardClicked event");
OnCardClicked?.Invoke(this);
}
}
}
#if UNITY_EDITOR
///
/// Editor-only: Preview a card from the assigned definition
///
public void PreviewFromDefinition()
{
if (editorCardDefinition == null)
{
Debug.LogWarning("[CardDisplay] No Card Definition assigned in Editor Tools.");
return;
}
CardData previewData = editorCardDefinition.CreateCardData();
SetupCard(previewData);
}
///
/// Editor-only: Clear the preview
///
public void ClearPreview()
{
cardData = null;
ClearCard();
}
#endif
}
#if UNITY_EDITOR
[CustomEditor(typeof(CardDisplay))]
public class CardDisplayEditor : Editor
{
public override void OnInspectorGUI()
{
DrawDefaultInspector();
CardDisplay display = (CardDisplay)target;
EditorGUILayout.Space();
EditorGUILayout.LabelField("Editor Preview Tools", EditorStyles.boldLabel);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Preview Card"))
{
display.PreviewFromDefinition();
EditorUtility.SetDirty(display);
}
if (GUILayout.Button("Clear Preview"))
{
display.ClearPreview();
EditorUtility.SetDirty(display);
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
EditorGUILayout.HelpBox(
"Assign a Card Definition in 'Editor Tools' section, then click 'Preview Card' to see how it will look at runtime.",
MessageType.Info
);
}
}
#endif
}