namespace TeleWave.Domain.Programming.Planning;

/// <summary>
/// Позиция каждого слота на время прогона.
///
/// Слот приходит в планировщик по экземпляру на вещательные сутки, и курсор у всех этих экземпляров
/// один и тот же — снимок <c>SlotState</c> из базы на начало прогона. Без общего хранилища слот
/// начинал бы вторник ровно с того места, что и понедельник, а фоновый слот, перекрытый в одни сутки
/// и свободный в другие, вёл бы вторую позицию независимо от основного цикла и переигрывал уже
/// поставленные серии.
/// </summary>
public sealed class SlotCursors
{
    private readonly Dictionary<Guid, PlanningCursor> _current = [];

    /// <summary>Где слот сейчас: позиция этого прогона, а до первого хода — снимок из базы.</summary>
    public PlanningCursor? Of(PlanningSlot slot) =>
        _current.TryGetValue(slot.SlotId, out var cursor) ? cursor : slot.Cursor;

    /// <summary>Тот же слот с актуальной позицией — в таком виде его и получают заполнители.</summary>
    public PlanningSlot Apply(PlanningSlot slot) => slot with { Cursor = Of(slot) };

    public void Advance(Guid slotId, PlanningElement element, int nextUnitIndex) =>
        _current[slotId] = new PlanningCursor(element.Kind, element.ElementId, nextUnitIndex);

    /// <summary>Что записать в состояние слотов: только те, что в этом прогоне действительно играли.</summary>
    public IReadOnlyList<PlanningCursorUpdate> Updates =>
        [
            .. _current.Select(pair => new PlanningCursorUpdate(
                pair.Key,
                pair.Value.ElementKind,
                pair.Value.ElementId,
                pair.Value.NextUnitIndex
            )),
        ];
}
