using System.Collections.Generic;
using System.Linq;
namespace KernelPanic.Combat
{
///
/// Manages draw, discard, and exhaust piles for a combat deck.
///
public sealed class DeckController
{
private readonly List _drawPile = new();
private readonly List _discardPile = new();
private readonly List _exhaustPile = new();
public IReadOnlyList DrawPile => _drawPile;
public IReadOnlyList DiscardPile => _discardPile;
public IReadOnlyList ExhaustPile => _exhaustPile;
public int AvailableToDrawCount => _drawPile.Count + _discardPile.Count;
public void Initialize(IEnumerable cards)
{
_drawPile.Clear();
_discardPile.Clear();
_exhaustPile.Clear();
if (cards != null)
{
_drawPile.AddRange(cards.Where(card => card != null));
}
ShuffleDrawPile();
}
public IReadOnlyList Draw(int count)
{
List drawn = new();
for (int i = 0; i < count; i++)
{
if (_drawPile.Count == 0)
{
ReshuffleDiscardIntoDraw();
}
if (_drawPile.Count == 0)
{
break;
}
int topIndex = _drawPile.Count - 1;
CardInstance card = _drawPile[topIndex];
_drawPile.RemoveAt(topIndex);
drawn.Add(card);
}
return drawn;
}
public bool TryDrawCheapestFromTop(int lookCount, out CardInstance card)
{
card = null;
if (lookCount <= 0)
{
return false;
}
if (_drawPile.Count == 0)
{
ReshuffleDiscardIntoDraw();
}
if (_drawPile.Count == 0)
{
return false;
}
int inspectCount = System.Math.Min(lookCount, _drawPile.Count);
int selectedIndex = _drawPile.Count - 1;
int selectedCost = CombatManager.GetCardCost(_drawPile[selectedIndex]);
for (int offset = 1; offset < inspectCount; offset++)
{
int index = _drawPile.Count - 1 - offset;
int cost = CombatManager.GetCardCost(_drawPile[index]);
if (cost < selectedCost)
{
selectedCost = cost;
selectedIndex = index;
}
}
card = _drawPile[selectedIndex];
_drawPile.RemoveAt(selectedIndex);
return card != null;
}
public void Discard(CardInstance card)
{
if (card != null)
{
_discardPile.Add(card);
}
}
public void AddToDrawPile(CardInstance card, bool shuffle)
{
if (card == null)
{
return;
}
_drawPile.Add(card);
if (shuffle)
{
ShuffleDrawPile();
}
}
public void Exhaust(CardInstance card)
{
if (card != null)
{
_exhaustPile.Add(card);
}
}
public void ShuffleDrawPile()
{
for (int i = _drawPile.Count - 1; i > 0; i--)
{
int swapIndex = RandomRoll.RollRange(0, i, RollContext.None);
(_drawPile[i], _drawPile[swapIndex]) = (_drawPile[swapIndex], _drawPile[i]);
}
}
public void ReshuffleDiscardIntoDraw()
{
if (_discardPile.Count == 0)
{
return;
}
_drawPile.AddRange(_discardPile);
_discardPile.Clear();
ShuffleDrawPile();
}
}
}