///|
/// 14-bolt-length-gauge
///
/// A physical "ruler" for bolts that includes embossed size markings and
/// 5 mm/10 mm scribed tick marks on the top face.
///
/// Usage (stdout):
///   moon run --target native examples/14-bolt-length-gauge -- > gauge.step
///
/// Usage (write file):
///   moon run --target native examples/14-bolt-length-gauge -- -o gauge.step
async fn main {
  let base_args_spec = {
    "length": @cli.opt_double(100.0, help="Length of the gauge (mm)", min=50.0),
    "width": @cli.opt_double(50.0, help="Width of the gauge (mm)", min=20.0),
    "height": @cli.opt_double(10.0, help="Height of the gauge (mm)", min=5.0),
  }
  let args_spec = @cli.with_translate(@common.with_output_args(base_args_spec))
  guard @cli.parse(
      args_spec,
      prog="14-bolt-length-gauge",
      description="Generate a bolt length gauge.",
    )
    is Some(args) else {
    return
  }
  let length = args.double("length")
  let width = args.double("width")
  let height = args.double("height")
  let output = @common.output_paths(args)
  let (tx, ty, tz) = match args.translate_xyz() {
    Some(v) => v
    None => {
      @cli.eprintln("error: invalid translation")
      abort("")
    }
  }

  //
  let bolt_sizes = [
    ("M3", 3.4),
    ("M4", 4.4),
    ("M5", 5.4),
    ("M6", 6.4),
    ("M8", 8.4),
  ]
  let slot_width = 10.0
  let font = @cad.load_font("baloo")
  let scribe_depth = 0.5
  let scribe_width = 0.8

  // 1. Through-holes shared by both layers (ruler slot and bolt holes).
  let through_holes = []

  // Ruler slot (as a through-hole)
  let slot_poly = [
    (-slot_width / 2.0, 5.0),
    (slot_width / 2.0, 5.0),
    (slot_width / 2.0, length - 5.0),
    (-slot_width / 2.0, length - 5.0),
  ].rev() // must be CW
  through_holes.push(slot_poly)

  // Bolt holes
  let hole_spacing = length / Double::from_int(bolt_sizes.length() + 1)
  for i in 0.. length - 2.0 {
      continue
    }
    let major = i % 2 == 0
    let len = if major { major_len } else { minor_len }
    if len <= 0.5 {
      continue
    }
    let x1 = tick_x0 + len
    scribe_holes.push(
      [
        (tick_x0, y - scribe_width / 2.0),
        (x1, y - scribe_width / 2.0),
        (x1, y + scribe_width / 2.0),
        (tick_x0, y + scribe_width / 2.0),
      ].rev(),
    )
  }

  // 3. Lower slab plus a thin marking layer. The scribe slots are holes in the
  // marking layer only, so the marks are shallow face notches, not cut-outs.
  let outer = @cad.Profile2D::rect(width, length).map(fn(p) {
    (p.0 - width / 2.0, p.1)
  })
  let lower = @cad.ExtrudedProfile::new(
      outer,
      height - scribe_depth,
      holes=through_holes,
    )
    .with_name("gauge-base")
    .with_color(@cad.Rgb::purple())
  let top_holes = through_holes.copy()
  top_holes.push_iter(scribe_holes.iter())
  let top = @cad.ExtrudedProfile::new(outer, scribe_depth, holes=top_holes)
    .with_name("gauge-marking-face")
    .with_color(@cad.Rgb::purple())
    .translate(z=height - scribe_depth)
  let mut design = @cad.Design::new(
      name="bolt-length-gauge",
      documentation=args.documentation(),
    )
    .add(lower)
    .add(top)

  // 4. Add labels
  for i in 0..