using System;
using System.Globalization;
using System.Linq;
namespace AMNet.Server;
///
/// Represents a storage location to load/read cards from
///
internal class CardPresenter
{
private readonly object _cardLock = new();
private StoredCard _currentCard;
public record StoredCard(byte[] Value, string OriginalValue, long ExpiresAt)
{
public bool Expired => Environment.TickCount64 >= ExpiresAt;
public override string ToString() => string.Join(" ", Enumerable.Range(0, 5).Select(x => OriginalValue.Substring(x * 4, 4)));
}
///
/// Returns the currently active card without clearing it
///
public StoredCard PeekActiveCard()
{
lock (_cardLock)
{
return _currentCard;
}
}
public StoredCard TakeActiveCard()
{
lock (_cardLock)
{
var card = _currentCard;
_currentCard = null;
return card;
}
}
///
/// Sets the card
///
/// The card id to set
/// How long the card should be presented to the game for in milliseconds
/// Whether the card was set successfully
public StoredCard SetCard(string cardId, long validFor = 5000)
{
// ensure the matrix code is 20-digits long, otherwise pad with zeros
var matrixCode = cardId.Replace(" ", "").PadLeft(20, '0');
var bytes = new byte[10];
for (var i = 0; i < bytes.Length; i++)
{
var value = matrixCode.Substring(i * 2, 2);
if (byte.TryParse(value, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var b))
{
bytes[i] = b;
}
else
{
return null;
}
}
var card = new StoredCard(bytes, matrixCode, Environment.TickCount64 + validFor);
lock (_cardLock)
{
_currentCard = card;
}
return card;
}
}