"""Ruler SVG generator for AGS Math instruments.

generate(length_cm, marked_cm, size) -> str  (self-contained SVG)

  - Steel-blue ruler body (rounded rectangle).
  - Ink cm graduation ticks with numbers 0..length_cm; half-cm minor ticks.
  - Optional crimson highlight line + dot at `marked_cm`.
  - D0ACAC rounded border frame; CSS-var style block.

  length_cm : integer length of the ruler in cm.
  marked_cm : optional value (0..length_cm) to highlight in crimson.
"""

STYLE = (
    "<style>svg{--crimson:#960000;--gold:#BF9237;--lime:#88C808;"
    "--steel:#4A6488;--cream:#FAF5EE;--ink:#2A2A2A;--border:#D0ACAC;}</style>"
)


def _fmt(v):
    if abs(v - round(v)) < 1e-9:
        return str(int(round(v)))
    return ('%g' % v)


def generate(length_cm=10, marked_cm=None, size=None):
    length_cm = int(length_cm)

    PAD = 36                 # left/right margin inside the frame
    STEP_PX = 42             # pixels per cm
    body_x = PAD
    ruler_w = length_cm * STEP_PX
    width = ruler_w + 2 * PAD
    height = 110
    body_y = 30
    body_h = 50              # ruler body height
    top = body_y
    bottom = body_y + body_h

    def xpos(cm):
        return body_x + cm * STEP_PX

    parts = []
    parts.append(
        f'<svg xmlns="http://www.w3.org/2000/svg" width="{int(width)}" '
        f'height="{height}" viewBox="0 0 {int(width)} {height}">'
    )
    parts.append(STYLE)

    # Border frame
    parts.append(
        f'<rect x="3" y="3" width="{int(width)-6}" height="{height-6}" rx="14" '
        f'ry="14" fill="none" stroke="var(--border)" stroke-width="3"/>'
    )

    # Steel-blue ruler body
    parts.append(
        f'<rect x="{body_x:.2f}" y="{top}" width="{ruler_w:.2f}" height="{body_h}" '
        f'rx="8" ry="8" fill="var(--steel)" stroke="var(--ink)" stroke-width="2"/>'
    )

    # Graduation ticks (cm majors with numbers, half-cm minors) from top edge
    for i in range(length_cm + 1):
        x = xpos(i)
        # major cm tick
        parts.append(
            f'<line x1="{x:.2f}" y1="{top}" x2="{x:.2f}" y2="{top+18}" '
            f'stroke="var(--ink)" stroke-width="2"/>'
        )
        parts.append(
            f'<text x="{x:.2f}" y="{top+34}" font-family="sans-serif" '
            f'font-size="13" fill="var(--ink)" text-anchor="middle">{_fmt(i)}</text>'
        )
        # half-cm minor tick (not past the end)
        if i < length_cm:
            xh = xpos(i + 0.5)
            parts.append(
                f'<line x1="{xh:.2f}" y1="{top}" x2="{xh:.2f}" y2="{top+10}" '
                f'stroke="var(--ink)" stroke-width="1"/>'
            )

    # Optional crimson highlight at marked_cm
    if marked_cm is not None:
        m = max(0.0, min(float(length_cm), float(marked_cm)))
        xm = xpos(m)
        parts.append(
            f'<line x1="{xm:.2f}" y1="{top-6}" x2="{xm:.2f}" y2="{bottom+6}" '
            f'stroke="var(--crimson)" stroke-width="2.5" stroke-linecap="round"/>'
        )
        parts.append(
            f'<circle cx="{xm:.2f}" cy="{bottom+6:.2f}" r="6" '
            f'fill="var(--crimson)" stroke="var(--cream)" stroke-width="1.5"/>'
        )

    parts.append('</svg>')
    return '\n'.join(parts)


if __name__ == '__main__':
    import os
    out = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'samples'))
    os.makedirs(out, exist_ok=True)
    samples = [
        dict(length_cm=10, marked_cm=6),
        dict(length_cm=15, marked_cm=12),
        dict(length_cm=6),
    ]
    for i, kw in enumerate(samples, 1):
        p = os.path.join(out, f'ruler_{i}.svg')
        with open(p, 'w', encoding='utf-8') as f:
            f.write(generate(**kw))
        print('wrote', p)
