///|
/// Small interoperable style vocabulary; arbitrary properties are outside MVP.
pub(all) enum Style {
  Plain
  Header
  Highlight
  Decimal2
  DateISO
}

///|
pub fn Cell::styled(self : Cell, style : Style) -> Cell {
  { value: self.value, formula: self.formula, style, }
}

///|
fn Style::id(self : Style) -> String {
  match self {
    Plain => "Plain"
    Header => "Header"
    Highlight => "Highlight"
    Decimal2 => "Decimal2"
    DateISO => "DateISO"
  }
}

///|
fn preset_styles() -> String {
  "--"
}

///|
/// Emit the requested ODF fixed column length in integer millimeters (1..500).
/// Viewer rounding, font metrics, zoom and physical print layout are not
/// guaranteed. No app-specific pixel/point compensation is applied.
pub fn Sheet::set_column_width(
  self : Sheet,
  col : Int,
  mm : Int,
) -> Unit raise OdsError {
  position(0, col)
  if mm < 1 || mm > 500 {
    raise Invalid("column width must be 1..500 mm")
  }
  let cols = if col + 1 > self.cols { col + 1 } else { self.cols }
  if self.rows * cols > 65536 {
    raise Invalid("sheet rendered grid exceeds 65536 cells")
  }
  self.widths.set(col, mm)
  self.cols = cols
}

///|
fn Workbook::column_styles(self : Workbook) -> String {
  let used : Map[Int, Bool] = Map([])
  for s in self.sheets {
    for _, mm in s.widths {
      used.set(mm, true)
    }
  }
  let b = StringBuilder()
  for mm in 1..<=500 {
    if used.contains(mm) {
      b.write_string(
        "",
      )
    }
  }
  b.to_string()
}

///|
/// Merge a zero-based rectangle. Covered values are never silently discarded.
pub fn Sheet::merge(
  self : Sheet,
  row : Int,
  col : Int,
  rows : Int,
  cols : Int,
) -> Unit raise OdsError {
  position(row, col)
  if rows < 1 || rows > 1024 || cols < 1 || cols > 128 || rows * cols == 1 {
    raise Invalid("merge must cover at least two cells within grid bounds")
  }
  position(row + rows - 1, col + cols - 1)
  if self.spans.length() >= 256 {
    raise Invalid("sheet exceeds 256 merges")
  }
  let nr = if row + rows > self.rows { row + rows } else { self.rows }
  let nc = if col + cols > self.cols { col + cols } else { self.cols }
  if nr * nc > 65536 {
    raise Invalid("sheet rendered grid exceeds 65536 cells")
  }
  for r in row..<(row + rows) {
    for c in col..<(col + cols) {
      if self.covered.contains((r, c)) || self.spans.contains((r, c)) {
        raise Invalid("overlapping merges")
      }
      if (r != row || c != col) && self.cells.contains((r, c)) {
        raise Invalid("merge would discard an existing cell")
      }
    }
  }
  for r in row..<(row + rows) {
    for c in col..<(col + cols) {
      if r != row || c != col {
        self.covered.set((r, c), true)
      }
    }
  }
  self.spans.set((row, col), (rows, cols))
  self.rows = nr
  self.cols = nc
}