using System;
using System.Collections.Generic;
using KernelPanic.Data;
namespace KernelPanic.Meta
{
public enum CardLoadoutFailureReason
{
None,
Full,
NotOwned,
Token,
Duplicate,
NotEquipped
}
///
/// Tracks equipped exclusive cards per owned distro without persistence or logging.
///
public sealed class CardLoadout
{
public const int MaxEquippedCards = 4;
private readonly IReadOnlyList ownedUnits;
private readonly Dictionary> equippedByDistro = new(StringComparer.OrdinalIgnoreCase);
public CardLoadout(IReadOnlyList ownedUnits)
{
this.ownedUnits = ownedUnits ?? Array.Empty();
}
public IReadOnlyList GetEquippedCardIds(string distroId)
{
return equippedByDistro.TryGetValue(distroId, out List equipped)
? equipped
: Array.Empty();
}
public bool HasLoadout(string distroId)
{
return !string.IsNullOrWhiteSpace(distroId) && equippedByDistro.ContainsKey(distroId);
}
public void EnsureLoadout(DistroDefinition distro)
{
if (distro == null || string.IsNullOrWhiteSpace(distro.Id) || HasLoadout(distro.Id))
{
return;
}
equippedByDistro[distro.Id] = new List();
}
public void ClearAll()
{
equippedByDistro.Clear();
}
public void ClearLoadout(DistroDefinition distro)
{
if (distro == null || string.IsNullOrWhiteSpace(distro.Id))
{
return;
}
equippedByDistro[distro.Id] = new List();
}
public bool TryLoad(string distroId, IEnumerable cardIds, out bool skippedInvalid)
{
skippedInvalid = false;
DistroDefinition distro = FindOwnedDistro(distroId);
if (distro == null)
{
skippedInvalid = true;
return false;
}
List equipped = new();
foreach (string cardId in cardIds ?? Array.Empty())
{
CardDefinition card = FindExclusiveCard(distro, cardId);
if (card == null || card.IsToken || equipped.Contains(card.Id))
{
skippedInvalid = true;
continue;
}
if (equipped.Count < MaxEquippedCards)
{
equipped.Add(card.Id);
}
else
{
skippedInvalid = true;
}
}
equippedByDistro[distro.Id] = equipped;
return true;
}
public bool TryEquip(string distroId, string cardId, out CardLoadoutFailureReason reason)
{
DistroDefinition distro = FindOwnedDistro(distroId);
if (distro == null)
{
reason = CardLoadoutFailureReason.NotOwned;
return false;
}
CardDefinition card = FindExclusiveCard(distro, cardId);
if (card == null)
{
reason = CardLoadoutFailureReason.NotOwned;
return false;
}
if (card.IsToken)
{
reason = CardLoadoutFailureReason.Token;
return false;
}
EnsureLoadout(distro);
List equipped = equippedByDistro[distro.Id];
if (equipped.Contains(card.Id))
{
reason = CardLoadoutFailureReason.Duplicate;
return false;
}
if (equipped.Count >= MaxEquippedCards)
{
reason = CardLoadoutFailureReason.Full;
return false;
}
equipped.Add(card.Id);
reason = CardLoadoutFailureReason.None;
return true;
}
public bool TryUnequip(string distroId, string cardId, out CardLoadoutFailureReason reason)
{
DistroDefinition distro = FindOwnedDistro(distroId);
if (distro == null)
{
reason = CardLoadoutFailureReason.NotOwned;
return false;
}
EnsureLoadout(distro);
List equipped = equippedByDistro[distro.Id];
if (!equipped.Remove(cardId))
{
reason = CardLoadoutFailureReason.NotEquipped;
return false;
}
reason = CardLoadoutFailureReason.None;
return true;
}
private DistroDefinition FindOwnedDistro(string distroId)
{
if (string.IsNullOrWhiteSpace(distroId))
{
return null;
}
for (int i = 0; i < ownedUnits.Count; i++)
{
DistroDefinition distro = ownedUnits[i];
if (distro != null && string.Equals(distro.Id, distroId, StringComparison.OrdinalIgnoreCase))
{
return distro;
}
}
return null;
}
private static CardDefinition FindExclusiveCard(DistroDefinition distro, string cardId)
{
if (distro == null || string.IsNullOrWhiteSpace(cardId))
{
return null;
}
for (int i = 0; i < distro.ExclusiveCards.Count; i++)
{
CardDefinition card = distro.ExclusiveCards[i];
if (card != null && string.Equals(card.Id, cardId, StringComparison.OrdinalIgnoreCase))
{
return card;
}
}
return null;
}
}
}