///|
fn PdfDocument::pdf_page_vertical_flip_matrix(
  self : PdfDocument,
  page : @page.PdfPage,
) -> @geometry.TransformMatrix raise @core.PdfError {
  let bounds = self.parse_rectangle(page.mediabox)
  @geometry.transform_scale(
    @geometry.point2(0.0, (bounds.min_y + bounds.max_y) / 2.0),
    1.0,
    -1.0,
  )
}

///|
fn PdfDocument::pdf_page_horizontal_flip_matrix(
  self : PdfDocument,
  page : @page.PdfPage,
) -> @geometry.TransformMatrix raise @core.PdfError {
  let bounds = self.parse_rectangle(page.mediabox)
  @geometry.transform_scale(
    @geometry.point2((bounds.min_x + bounds.max_x) / 2.0, 0.0),
    -1.0,
    1.0,
  )
}

///|
fn PdfDocument::pdf_page_flip_pages(
  self : PdfDocument,
  page_numbers : ArrayView[Int],
  context : String,
  fast : Bool,
  matrix_of_page : (@page.PdfPage) -> @geometry.TransformMatrix raise @core.PdfError,
) -> PdfDocument raise @core.PdfError {
  pdf_page_box_validate_page_numbers(page_numbers, self.endpage(), context)
  let pages = self.pages_of_pagetree()
  let selected_pages = @core.pdf_number_set(page_numbers)
  let rewritten : Array[@page.PdfPage] = Array(capacity=pages.length())
  let matrices : Array[(Int, @geometry.TransformMatrix)] = Array(
    capacity=page_numbers.length(),
  )
  for index in 0.. PdfDocument raise @core.PdfError {
  self.pdf_page_flip_pages(page_numbers, "flip_pages_vertically", fast, page => {
    self.pdf_page_vertical_flip_matrix(page)
  })
}

///|
/// Compatibility method using cpdfpage's `vflip_pdf` name.
pub fn PdfDocument::vflip_pdf(
  self : PdfDocument,
  page_numbers : ArrayView[Int],
  fast? : Bool = false,
) -> PdfDocument raise @core.PdfError {
  self.flip_pages_vertically(page_numbers, fast~)
}

///|
/// Compatibility wrapper for `PdfDocument::flip_pages_vertically`.
pub fn pdf_vflip_pdf(
  document : PdfDocument,
  page_numbers : ArrayView[Int],
  fast? : Bool = false,
) -> PdfDocument raise @core.PdfError {
  document.vflip_pdf(page_numbers, fast~)
}

///|
/// Flip selected pages horizontally around the horizontal centre of each page's
/// `/MediaBox`.
///
/// This ports cpdf's `hflip_pdf`: page content, annotations, pattern matrices,
/// and destination coordinates are transformed, while page boxes are left
/// unchanged.
pub fn PdfDocument::flip_pages_horizontally(
  self : PdfDocument,
  page_numbers : ArrayView[Int],
  fast? : Bool = false,
) -> PdfDocument raise @core.PdfError {
  self.pdf_page_flip_pages(page_numbers, "flip_pages_horizontally", fast, page => {
    self.pdf_page_horizontal_flip_matrix(page)
  })
}

///|
/// Compatibility method using cpdfpage's `hflip_pdf` name.
pub fn PdfDocument::hflip_pdf(
  self : PdfDocument,
  page_numbers : ArrayView[Int],
  fast? : Bool = false,
) -> PdfDocument raise @core.PdfError {
  self.flip_pages_horizontally(page_numbers, fast~)
}

///|
/// Compatibility wrapper for `PdfDocument::flip_pages_horizontally`.
pub fn pdf_hflip_pdf(
  document : PdfDocument,
  page_numbers : ArrayView[Int],
  fast? : Bool = false,
) -> PdfDocument raise @core.PdfError {
  document.hflip_pdf(page_numbers, fast~)
}