///|
/// Append another table's records, using the first table's configuration.
pub struct Concat {
  priv table : Table
  priv horizontal : Bool
  priv empty_cell : String
}

///|
/// Append columns from another table.
pub fn Concat::horizontal(table : Table) -> Concat {
  { table, horizontal: true, empty_cell: "", }
}

///|
/// Append rows from another table.
pub fn Concat::vertical(table : Table) -> Concat {
  { table, horizontal: false, empty_cell: "", }
}

///|
/// Fill the first table's newly introduced rows (horizontal concatenation)
/// or columns (vertical concatenation). Other missing cells remain empty.
pub fn Concat::default_cell(self : Concat, text : String) -> Concat {
  { ..self, empty_cell: text, }
}

///|
/// Concatenate records, keeping the receiving table's style and cell settings.
///
/// ```mbt check
/// test {
///   let table = @tabular.Table::from_rows([["a"]])
///   let other = @tabular.Table::from_rows([["b"], ["c"]])
///   table.concat(@tabular.Concat::horizontal(other).default_cell("?")) |> ignore
///   assert_eq(table.rows, [["a", "b"], ["?", "c"]])
/// }
/// ```
pub fn Table::concat(self : Table, concat : Concat) -> Table {
  let lhs = @papergrid.IterRecords::new(self.rows)
  let rhs = @papergrid.IterRecords::new(concat.table.rows)
  let left_rows = lhs.count_rows()
  let left_cols = lhs.count_cols()
  let right_rows = rhs.count_rows()
  let right_cols = rhs.count_cols()
  self.rows = if concat.horizontal {
    Array::makei(Int::max(left_rows, right_rows), row => {
      Array::makei(left_cols + right_cols, col => {
        if col >= left_cols && row < right_rows {
          rhs.get_cell(row, col - left_cols)
        } else if row >= left_rows {
          concat.empty_cell
        } else if col < left_cols {
          lhs.get_cell(row, col)
        } else {
          ""
        }
      })
    })
  } else {
    Array::makei(left_rows + right_rows, row => {
      Array::makei(Int::max(left_cols, right_cols), col => {
        if row >= left_rows && col < right_cols {
          rhs.get_cell(row - left_rows, col)
        } else if col >= left_cols {
          concat.empty_cell
        } else if row < left_rows {
          lhs.get_cell(row, col)
        } else {
          ""
        }
      })
    })
  }
  self.finish_legacy_change()
}