using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace AppleHills.Data.CardSystem
{
///
/// Manages the player's collection of cards and booster packs
///
[Serializable]
public class CardInventory
{
// Dictionary of collected cards indexed by definition ID
[SerializeField] private Dictionary collectedCards = new Dictionary();
// Number of unopened booster packs the player has
[SerializeField] private int boosterPackCount;
// Additional lookup dictionaries (not serialized)
[NonSerialized] private Dictionary> cardsByZone = new Dictionary>();
[NonSerialized] private Dictionary> cardsByRarity = new Dictionary>();
// Properties with public getters
public Dictionary CollectedCards => collectedCards;
public int BoosterPackCount
{
get => boosterPackCount;
set => boosterPackCount = value;
}
// Constructor initializes empty dictionaries
public CardInventory()
{
// Initialize dictionaries for all enum values so we never have to check for null
foreach (CardZone zone in Enum.GetValues(typeof(CardZone)))
{
cardsByZone[zone] = new List();
}
foreach (CardRarity rarity in Enum.GetValues(typeof(CardRarity)))
{
cardsByRarity[rarity] = new List();
}
}
///
/// Get all cards in the player's collection as a list
///
public List GetAllCards()
{
return collectedCards.Values.ToList();
}
///
/// Clears all cards from the inventory
/// Primarily used for testing
///
public void ClearAllCards()
{
collectedCards.Clear();
// Clear lookup dictionaries
foreach (var zone in cardsByZone.Keys)
{
cardsByZone[zone].Clear();
}
foreach (var rarity in cardsByRarity.Keys)
{
cardsByRarity[rarity].Clear();
}
}
///
/// Get cards filtered by zone
///
public List GetCardsByZone(CardZone zone)
{
return new List(cardsByZone[zone]);
}
///
/// Get cards filtered by rarity
///
public List GetCardsByRarity(CardRarity rarity)
{
return new List(cardsByRarity[rarity]);
}
///
/// Add a card to the inventory (or increase the copies if already owned)
///
public void AddCard(CardData card)
{
if (card == null) return;
if (collectedCards.TryGetValue(card.DefinitionId, out CardData existingCard))
{
// Increase copies of existing card
existingCard.CopiesOwned++;
}
else
{
// Add new card to collection
var newCard = new CardData(card);
collectedCards[card.DefinitionId] = newCard;
// Add to lookup dictionaries
cardsByZone[newCard.Zone].Add(newCard);
cardsByRarity[newCard.Rarity].Add(newCard);
}
}
///
/// Update card zone and rarity indexes when a card changes
///
public void UpdateCardProperties(CardData card, CardZone oldZone, CardRarity oldRarity)
{
// Only needed if the card's zone or rarity actually changed
if (oldZone != card.Zone)
{
cardsByZone[oldZone].Remove(card);
cardsByZone[card.Zone].Add(card);
}
if (oldRarity != card.Rarity)
{
cardsByRarity[oldRarity].Remove(card);
cardsByRarity[card.Rarity].Add(card);
}
}
///
/// Get a specific card from the collection by definition ID
///
public CardData GetCard(string definitionId)
{
return collectedCards.TryGetValue(definitionId, out CardData card) ? card : null;
}
///
/// Check if the player has a specific card
///
public bool HasCard(string definitionId)
{
return collectedCards.ContainsKey(definitionId);
}
///
/// Get total number of unique cards in collection
///
public int GetUniqueCardCount()
{
return collectedCards.Count;
}
///
/// Get total number of cards including copies
///
public int GetTotalCardCount()
{
return collectedCards.Values.Sum(card => card.CopiesOwned);
}
///
/// Get number of cards in a specific zone
///
public int GetZoneCardCount(CardZone zone)
{
return cardsByZone[zone].Count;
}
///
/// Get number of cards of a specific rarity
///
public int GetRarityCardCount(CardRarity rarity)
{
return cardsByRarity[rarity].Count;
}
///
/// Get cards sorted by collection index (for album view)
///
public List GetCardsSortedByIndex()
{
return collectedCards.Values
.OrderBy(card => card.CollectionIndex)
.ToList();
}
///
/// Check if there's a complete collection for a specific zone
///
public bool IsZoneCollectionComplete(CardZone zone, List allAvailableCards)
{
int availableInZone = allAvailableCards.Count(card => card.Zone == zone);
int collectedInZone = cardsByZone[zone].Count;
return availableInZone > 0 && collectedInZone >= availableInZone;
}
///
/// Adds booster packs to the inventory
///
public void AddBoosterPacks(int count)
{
boosterPackCount += count;
}
///
/// Use a single booster pack (returns true if successful)
///
public bool UseBoosterPack()
{
if (boosterPackCount <= 0) return false;
boosterPackCount--;
return true;
}
}
}