// lib/editor/layout/double_page_layout.dart
//
// Two-up (spread) layout foundation for book-like reading (F2/F3 — the user's
// explicit "two-page spread" ask). Pages are grouped into spread ROWS; each row
// then stacks vertically exactly like continuous-single, so windowing reuses
// PageStackMetrics on the row heights.
//
// Pure geometry (no widgets / pdfrx): the row-mounting widget is device-gated;
// the pairing + row-height math is here, fully unit-tested. Building it ahead of
// its phase is zero-rework-risk (it is not rendering and the P0.5 perf gate
// can't invalidate pure geometry).

import 'page_viewport.dart';
import '../pdf/pdf_document_source.dart';

/// Groups page indices into two-up spread rows. With [coverAlone], page 0 sits
/// on its own row (a book cover / title page) and the rest pair 1-2, 3-4, …;
/// otherwise pages pair from 0. A trailing odd page occupies a single-page row.
List<List<int>> pairIntoRows(int pageCount, {bool coverAlone = false}) {
  assert(pageCount >= 0);
  final rows = <List<int>>[];
  var i = 0;
  if (coverAlone && pageCount > 0) {
    rows.add(<int>[0]);
    i = 1;
  }
  while (i < pageCount) {
    if (i + 1 < pageCount) {
      rows.add(<int>[i, i + 1]);
      i += 2;
    } else {
      rows.add(<int>[i]);
      i += 1;
    }
  }
  return rows;
}

/// Height of each spread row when each page is fit to HALF of [columnWidth]
/// (two pages share the column). A row's height is the tallest of its pages so
/// both pages sit on a common baseline. Non-positive page widths contribute 0.
List<double> spreadRowHeights(
  PageDocumentSource source,
  double columnWidth,
  List<List<int>> rows,
) {
  assert(columnWidth >= 0);
  final half = columnWidth / 2;
  return rows.map((row) {
    var tallest = 0.0;
    for (final pageIndex in row) {
      final size = source.pageSize(pageIndex);
      if (size.width <= 0) continue;
      final fit = half * (size.height / size.width);
      if (fit > tallest) tallest = fit;
    }
    return tallest;
  }).toList(growable: false);
}

/// Continuous-DOUBLE stacking metrics: pair pages into spread rows, then stack
/// the rows vertically. [PageStackMetrics.visibleRange] over the result yields
/// the visible ROW range; map rows back to pages via the [pairIntoRows] result.
PageStackMetrics spreadStackMetrics(
  PageDocumentSource source,
  double columnWidth, {
  bool coverAlone = false,
  double gap = 0.0,
}) {
  final rows = pairIntoRows(source.pageCount, coverAlone: coverAlone);
  return PageStackMetrics(
    pageHeights: spreadRowHeights(source, columnWidth, rows),
    gap: gap,
  );
}
