namespace TeleWave.Domain.Programming;

/// <summary>
/// Состояние слота: где остановились в текущем элементе. Курсор хранит ссылку на элемент, а не
/// числовой индекс в группе, — при удалении позиции из группы он корректно переезжает на следующую,
/// а не сдвигает всё.
///
/// Состояние существует потому, что сетка эластичная: сколько единиц уйдёт за один выход слота,
/// зависит от фактических длительностей, и вычислить это арифметически от эпохи нельзя.
/// </summary>
public class SlotState
{
    public Guid SlotId { get; private set; }
    public GroupElementKind? CurrentElementKind { get; private set; }
    public Guid? CurrentElementId { get; private set; }

    /// <summary>Позиция следующей единицы внутри текущего элемента.</summary>
    public int NextUnitIndex { get; private set; }

    private SlotState() { }

    public static SlotState Create(Guid slotId) => new() { SlotId = slotId, NextUnitIndex = 0 };

    /// <summary>Продолжить текущий элемент со следующей единицы.</summary>
    public void Advance(int nextUnitIndex) => NextUnitIndex = Math.Max(0, nextUnitIndex);

    /// <summary>Перейти к другому элементу, начав его с указанной единицы.</summary>
    public void MoveTo(GroupElementKind kind, Guid elementId, int nextUnitIndex = 0)
    {
        CurrentElementKind = kind;
        CurrentElementId = elementId;
        NextUnitIndex = Math.Max(0, nextUnitIndex);
    }

    /// <summary>Забыть текущий элемент — например, когда он исчез из группы.</summary>
    public void Reset()
    {
        CurrentElementKind = null;
        CurrentElementId = null;
        NextUnitIndex = 0;
    }
}
