///|
/// 10-polygon-knob
///
/// A parametric polygon knob with a custom polygon hole for a shaft.
///
/// Usage (stdout):
///   moon run --target native examples/10-polygon-knob -- > knob.step
///
/// Usage (write file):
///   moon run --target native examples/10-polygon-knob -- -o knob.step
async fn main {
  let base_args_spec = {
    "sides": @cli.opt_double(
      6.0,
      help="Number of sides for the knob (e.g. 6 for hexagon)",
      min=3.0,
    ),
    "diameter": @cli.opt_double(
      30.0,
      help="Knob outer diameter (mm)",
      min=0.0,
      min_exclusive=true,
    ),
    "height": @cli.opt_double(
      15.0,
      help="Knob height (mm)",
      min=0.0,
      min_exclusive=true,
    ),
    "holeSides": @cli.opt_double(
      6.0,
      help="Number of sides for the shaft hole",
      min=3.0,
    ),
    "holeDiameter": @cli.opt_double(
      6.35,
      help="Shaft hole diameter (mm)",
      min=0.0,
      min_exclusive=true,
    ),
    "holeRotation": @cli.opt_double(0.0, help="Shaft hole rotation (degrees)"),
  }
  let args_spec = @cli.with_translate(@common.with_output_args(base_args_spec))
  guard @cli.parse(
      args_spec,
      prog="10-polygon-knob",
      description="Generate a parametric polygon knob.",
    )
    is Some(args) else {
    return
  }
  let sides = args.double("sides").to_int()
  let diameter = args.double("diameter")
  let height = args.double("height")
  let hole_sides = args.double("holeSides").to_int()
  let hole_diameter = args.double("holeDiameter")
  let hole_rotation = args.double("holeRotation")
  let output = @common.output_paths(args)
  let (tx, ty, tz) = match args.translate_xyz() {
    Some(v) => v
    None => {
      @cli.eprintln("error: invalid translation")
      abort("")
    }
  }

  // Validate hole fits in knob
  if hole_diameter >= diameter {
    @cli.eprintln("error: holeDiameter must be less than diameter")
    abort("")
  }

  //
  let knob = polygon_knob(
      sides,
      diameter,
      height,
      hole_sides,
      hole_diameter,
      hole_rotation~,
    )
    .with_name("polygon-knob")
    .with_color(@cad.Rgb::cyan())
    .translate(x=tx, y=ty, z=tz)

  //
  let design = @cad.Design::new(
    name="polygon-knob",
    documentation=args.documentation(),
  ).add(knob)
  @common.write_output(design, output)
}

///|
fn polygon_knob(
  sides : Int32,
  diameter : Double,
  height : Double,
  hole_sides : Int32,
  hole_diameter : Double,
  hole_rotation~ : Double = 0.0,
) -> @cad.Shape {
  let outer = @cad.Profile2D::polygon(sides, diameter)
  let hole = @cad.Profile2D::polygon(
    hole_sides,
    hole_diameter,
    rotation=hole_rotation,
  )
  // Hole must be reversed (CW) for standard STEP orientation if outer is CCW.
  let hole_reversed = hole.rev()
  @cad.ExtrudedProfile::new(outer, height, holes=[hole_reversed])
}