///|
/// `Cmd` represents an SVG command along with its parameters.
struct Cmd {
  c : String
  p : Params
} derive(Debug, Eq)

///|
pub impl Show for Cmd with fn output(self, logger) {
  let { c, p } = self
  logger.write_string(
    (
      $|{c: \{c.escape(quote=true)}, p: \{p}}
    ),
  )
}

///|
test "Cmd show interface" {
  let cmd = { c: "M", p: Params([10.0, 20.0]) }
  inspect(
    cmd,
    content=(
      #|{c: "M", p: Params([10, 20])}
    ),
  )
}

///|
let split_re : @regexp.Regexp = try! @regexp.compile(
  "^([MLCQZ])([0-9\\.\\-,\\s]*)",
  flags="m",
)

///|
/// `split_path` splits an SVG path into an array of individual commands.
fn split_path(d : String) -> Array[Cmd] raise FontError {
  let mut d = d
  let cmds = []
  while d.length() > 0 {
    let match_result = split_re
      .match_(d)
      .unwrap_or_error(
        FontError("split_path: unable to parse SVG params: \{d}"),
      )
    match match_result.results() {
      [_, Some(c), Some(p)] => {
        d = d.unsafe_substring(start=c.length() + p.length(), end=d.length())
        let c = c.to_owned()
        let p = parse_params(p.to_owned())
        cmds.push({ c, p })
      }
      _ => raise FontError("split_path: unable to split SVG path \{d}")
    }
  }
  cmds
}

///|
test "split_path" {
  let d =
    #|M507 24L48 24L48 530L395 530L395 625L48 625L48 723L507
    #|723L507 24ZM395 269L395 433L138 433L138 269L395 269Z
  let got = split_path(d)
  let want = [
    { c: "M", p: Params([507.0, 24.0]) },
    { c: "L", p: Params([48.0, 24.0]) },
    { c: "L", p: Params([48.0, 530.0]) },
    { c: "L", p: Params([395.0, 530.0]) },
    { c: "L", p: Params([395.0, 625.0]) },
    { c: "L", p: Params([48.0, 625.0]) },
    { c: "L", p: Params([48.0, 723.0]) },
    { c: "L", p: Params([507.0, 723.0]) },
    { c: "L", p: Params([507.0, 24.0]) },
    { c: "Z", p: Params([]) },
    { c: "M", p: Params([395.0, 269.0]) },
    { c: "L", p: Params([395.0, 433.0]) },
    { c: "L", p: Params([138.0, 433.0]) },
    { c: "L", p: Params([138.0, 269.0]) },
    { c: "L", p: Params([395.0, 269.0]) },
    { c: "Z", p: Params([]) },
  ]
  @debug.assert_eq(got, want)
}