/**
 * Чистая логика окна видимых строк вертикального списка: без Pixi,
 * тестируется изолированно (по образцу ListCursor). MenuList использует её
 * для скролла длинных списков: курсор всегда в окне, окно — в [0, count].
 */
export class ListScroll {
    /** Индекс первой видимой строки. */
    offset = 0;
    /** Число элементов (из последнего sync) — для clamped. */
    private count = 0;

    constructor(readonly rows: number) {}

    /** Пересчёт окна под выбранный индекс; возвращает offset. */
    sync(index: number, count: number): number {
        this.count = count;
        const max = Math.max(0, count - this.rows);
        if (this.offset > max) this.offset = max; // список пересобран короче
        if (index < this.offset) this.offset = index; // курсор ушёл выше окна
        else if (index >= this.offset + this.rows) {
            this.offset = Math.min(max, index - this.rows + 1); // ниже окна
        }
        return this.offset;
    }

    /** Индекс первой видимой строки. */
    get first(): number {
        return this.offset;
    }

    /** Исключающая граница окна (после последней видимой строки). */
    get last(): number {
        return Math.min(this.count, this.offset + this.rows);
    }

    /** Список короче окна: всё видно, прокрутки нет. */
    get clamped(): boolean {
        return this.count <= this.rows;
    }
}