///|
/// 25-miter-saw-angle-template
///
/// A set of printable angle templates for calibrating miter saw joints.
/// Each wedge represents a standard joint angle.
///
/// Usage (stdout):
///   moon run --target native examples/25-miter-saw-angle-template -- --thickness 5 > templates.step
async fn main {
  let base_args_spec = {
    "angles": @cli.opt_string(
      short='a',
      help="Comma-separated list of angles (degrees). Default: 15,22.5,30,45",
    ),
    "size": @cli.opt_double(
      50.0,
      help="Length of the wedge edges (mm)",
      min=10.0,
    ),
    "thickness": @cli.opt_double(
      5.0,
      help="Thickness of the templates (mm)",
      min=1.0,
    ),
    "holeDiameter": @cli.opt_double(
      5.0,
      help="Diameter of the optional hanging hole (mm)",
      min=0.0,
    ),
  }
  let args_spec = @cli.with_translate(@common.with_output_args(base_args_spec))
  guard @cli.parse(
      args_spec,
      prog="25-miter-saw-angle-template",
      description="Generate miter saw angle templates.",
    )
    is Some(args) else {
    return
  }
  let angles_str = args.string_opt("angles").unwrap_or("15,22.5,30,45")
  let size = args.double("size")
  let thickness = args.double("thickness")
  let hole_dia = args.double("holeDiameter")
  let output = @common.output_paths(args)
  let (tx, ty, tz) = match args.translate_xyz() {
    Some(v) => v
    None => {
      @cli.eprintln("error: invalid translation")
      return
    }
  }
  let angles = parse_angles(angles_str)
  let design = miter_templates(
    angles,
    size,
    thickness,
    hole_dia,
    args.documentation(),
  ).translate(x=tx, y=ty, z=tz)
  @common.write_output(design, output)
}

///|
fn parse_angles(s : String) -> Array[Double] {
  let parts = s.split(",")
  let out = []
  for p in parts {
    let val = @string.parse_double(p.trim().to_owned()) catch { _ => 0.0 }
    if val > 0.0 && val < 90.0 {
      out.push(val)
    }
  }
  if out.length() == 0 {
    [15.0, 22.5, 30.0, 45.0]
  } else {
    out
  }
}

///|
async fn miter_templates(
  angles : Array[Double],
  size : Double,
  thickness : Double,
  hole_dia : Double,
  documentation : String,
) -> @cad.Design {
  let mut design = @cad.Design::new(name="miter-templates", documentation~)
  let spacing = size + 10.0
  let font = @cad.load_font("baloo")
  for i, angle in angles {
    let x_off = Double::from_int(i) * spacing

    // Wedge profile
    let angle_rad = angle * @math.PI / 180.0
    let h_max = size * @math.tan(angle_rad)
    let base_h = 10.0
    let wedge_poly = [
      (0.0, 0.0),
      (size, 0.0),
      (size, base_h + h_max),
      (0.0, base_h),
    ]
    let mut profile = @cad.Profile2D::new(wedge_poly)
    if hole_dia > 0.0 {
      let hx = size * 0.8
      let hy = base_h * 0.5
      let hole = @cad.Profile2D::circle(hole_dia)
        .map(fn(p) { (p.0 + hx, p.1 + hy) })
        .rev()
      profile = profile.add_hole(hole)
    }
    let wedge = @cad.ExtrudedProfile::new(
        profile.outer,
        thickness,
        holes=profile.holes,
      )
      .with_name("wedge-\{angle}")
      .with_color(@cad.Rgb::purple())
      .translate(x=x_off)
    design = design.add(wedge)

    // Label on the large side face
    let label_text = "\{angle}°"
    design = design.add_text_on_face(
      wedge,
      label_text,
      Top,
      font,
      font_size=base_h * 0.6,
      offset_x=size * 0.3,
      offset_y=0.0,
      color=@cad.Rgb::white(),
    )
  }
  design
}