///|
fn path_resource_u64(value : Int) -> Bytes {
  Int::max(0, value).to_uint64().to_be_bytes()
}

///|
fn path_resource_bytes(value : Bytes) -> Bytes {
  value.length().to_uint64().to_be_bytes() + value
}

///|
fn PathFillType::resource_name(self : PathFillType) -> Bytes {
  match self {
    Winding => b"winding"
    EvenOdd => b"even-odd"
    InverseWinding => b"inverse-winding"
    InverseEvenOdd => b"inverse-even-odd"
  }
}

///|
fn Point::path_resource_id(self : Point) -> Bytes {
  self.x.to_be_bytes() + self.y.to_be_bytes()
}

///|
fn PathVerb::resource_id(self : PathVerb) -> Bytes {
  match self {
    MoveTo(point) => b"M" + point.path_resource_id()
    LineTo(point) => b"L" + point.path_resource_id()
    QuadTo(control, end) =>
      b"Q" + control.path_resource_id() + end.path_resource_id()
    ConicTo(control, end, weight) =>
      b"C" +
      control.path_resource_id() +
      end.path_resource_id() +
      weight.to_be_bytes()
    CubicTo(control0, control1, end) =>
      b"U" +
      control0.path_resource_id() +
      control1.path_resource_id() +
      end.path_resource_id()
    Close => b"Z"
  }
}

///|
fn Path::resource_id(self : Path) -> Bytes {
  if self.is_empty() || !self.is_finite() {
    b""
  } else {
    let mut id = b"moui_skia:path:v1" +
      path_resource_bytes(self.fill_type.resource_name()) +
      path_resource_u64(self.verbs.length())
    for verb in self.verbs {
      id = id + path_resource_bytes(verb.resource_id())
    }
    id
  }
}

///|
pub fn Path::resource_key(self : Path) -> RendererResourceKey {
  RendererResourceKey::path(self.resource_id())
}

///|
pub fn Path::resource_descriptor(
  self : Path,
  byte_size? : Int64 = -1L,
) -> RendererResourceDescriptor {
  let id = self.resource_id()
  let measured_byte_size = if byte_size < 0L {
    id.length().to_int64()
  } else {
    byte_size
  }
  RendererResourceDescriptor::path(id, byte_size=measured_byte_size)
}