///|
/// New ids and the retained original edge after a local edge split.
pub(all) struct SplitReport {
  vertex : Int
  retained_edge : EdgeId
  created_edges : Array[EdgeId]
  created_faces : Array[Int]
} derive(Debug)

///|
pub extend SplitReport with @debug.Debug::{to_repr}

///| Split an edge; fraction is measured from edge_vertices().0 towards .1.

///|
/// All recoverable errors occur before mutation. Other element ids are retained.
pub fn Mesh::split_edge(
  self : Mesh,
  edge : EdgeId,
  fraction? : Double = 0.5,
) -> SplitReport raise SurfaceError {
  let (a, b) = self.edge_vertices(edge)
  if !finite(fraction) || fraction <= 0.0 || fraction >= 1.0 {
    raise InvalidArgument(
      "split fraction must be strictly between zero and one",
    )
  }
  let EdgeId(e) = edge
  let h = if self.halfedges[2 * e].face >= 0 { 2 * e } else { 2 * e + 1 }
  let t = opposite(h)
  let boundary = self.halfedges[t].face < 0
  let added_faces = if boundary { 1 } else { 2 }
  if self.vertex_count() >= self.limits.max_vertices {
    raise LimitExceeded("split vertices")
  }
  if self.face_count() + added_faces > self.limits.max_output_faces {
    raise LimitExceeded("split faces")
  }
  let p = Vec3::{
    x: lerp_scalar(self.vertices[a].x, self.vertices[b].x, fraction),
    y: lerp_scalar(self.vertices[a].y, self.vertices[b].y, fraction),
    z: lerp_scalar(self.vertices[a].z, self.vertices[b].z, fraction),
  }
  let u = self.halfedges[h].origin
  let v = self.halfedges[t].origin
  let ln = self.halfedges[h].next
  let lp = self.halfedges[ln].next
  let w = self.halfedges[lp].origin
  if !finite(p.x) ||
    !finite(p.y) ||
    !finite(p.z) ||
    degenerate(self.vertices[u], p, self.vertices[w]) ||
    degenerate(p, self.vertices[v], self.vertices[w]) {
    raise NumericalFailure("split would create degenerate geometry")
  }
  let rn = self.halfedges[t].next
  let rp = self.halfedges[rn].next
  let x = if boundary { -1 } else { self.halfedges[rp].origin }
  if !boundary &&
    (
      degenerate(p, self.vertices[u], self.vertices[x]) ||
      degenerate(self.vertices[v], p, self.vertices[x])
    ) {
    raise NumericalFailure("split would create degenerate geometry")
  }
  let mut boundary_prev = -1
  if boundary {
    let mut current = ln
    for _ in 0.. Double {
  if (a >= 0.0 && b >= 0.0) || (a <= 0.0 && b <= 0.0) {
    a + (b - a) * t
  } else {
    (1.0 - t) * a + t * b
  }
}

///|
fn Mesh::append_edge(self : Mesh, a : Int, b : Int) -> Int {
  let h = self.halfedges.length()
  self.halfedges.push({ origin: a, next: -1, face: -1, })
  self.halfedges.push({ origin: b, next: -1, face: -1, })
  self.edge_lookup[edge_key(a, b)] = h / 2
  h
}

///|
fn Mesh::set_triangle(
  self : Mesh,
  face : Int,
  a : Int,
  b : Int,
  c : Int,
) -> Unit {
  self.faces[face] = a
  for (h, next) in [(a, b), (b, c), (c, a)] {
    self.halfedges[h].face = face
    self.halfedges[h].next = next
  }
}