"""Rewrite a vsketch or vpype SVG so that its coordinates are millimeters.

vsketch saves its coordinates in CSS pixels (96 per inch) and only states the
page size in centimeters. Plotter tools that read the numbers as millimeters
then draw 3.78 times too large. This script writes the same lines with one
user unit per millimeter.

Usage:  python svg_to_mm.py input.svg output.svg
Needs vpype, which comes with vsketch.
"""
import sys
from pathlib import Path

import vpype as vp

PX_PER_MM = vp.convert_length("1mm")  # 3.7795...: CSS pixels per millimeter


def to_mm(source: str, target: str) -> None:
    doc = vp.read_multilayer_svg(source, quantization=0.1)  # in pixels
    if doc.page_size is None:
        sys.exit(f"{source}: no page size found")
    width = doc.page_size[0] / PX_PER_MM
    height = doc.page_size[1] / PX_PER_MM

    paths = []
    for layer in doc.layers.values():
        for line in layer:
            points = [f"{p.real / PX_PER_MM:.3f},{p.imag / PX_PER_MM:.3f}" for p in line]
            paths.append(f'  <path d="M {points[0]} L {" ".join(points[1:])}"/>')

    svg = [
        '<?xml version="1.0" encoding="UTF-8"?>',
        f'<svg xmlns="http://www.w3.org/2000/svg" width="{width:.1f}mm" '
        f'height="{height:.1f}mm" viewBox="0 0 {width:.1f} {height:.1f}">',
        '<g fill="none" stroke="black" stroke-width="0.3">',
        *paths,
        "</g>",
        "</svg>",
    ]
    Path(target).write_text("\n".join(svg) + "\n", encoding="utf-8")
    print(f"{target}: {width:.0f} x {height:.0f} mm, {len(paths)} lines")


if __name__ == "__main__":
    if len(sys.argv) != 3:
        sys.exit("usage: python svg_to_mm.py input.svg output.svg")
    to_mm(sys.argv[1], sys.argv[2])
