r"""RotatoCAM post-processor for Genmitsu / SainSmart machines with a rotary axis.

Drop this file into:      %USERPROFILE%\.rotatocam\posts\
Then restart RotatoCAM.   It appears in the Controller dropdown as
                          "genmitsu (custom)".

Covers the 4040-PRO, 3030 PROVer MAX and any other Genmitsu running their
"Grbl V2.0" controller with the 4th-axis rotary kit.

WHY THIS EXISTS
---------------
Genmitsu machines do not run stock GRBL. Their firmware is grbl 1.1f ported to
ARM32 with a real 4th axis. Picking plain "grbl" in RotatoCAM refuses any rotary
toolpath, which is correct for a 3018 but wrong for a Genmitsu.

THE AXIS LETTER IS A, AND ONLY A
--------------------------------
Confirmed by reading the shipped firmware: the offline controller jogs X, Y, Z
and A, and the settings code emits exactly four axis letters (X, Y, Z, A) with no
B and no C anywhere. So this post pins the rotary letter to A and ignores the
job's rotary-letter setting. A job set up for C would otherwise emit words the
machine cannot act on, and the rotary would sit still while the cutter moved.

Everything else matches the grblHAL post: millimetres, absolute, G93 inverse-time
on rotary blocks and G94 on linear moves, M30 to end, ';' comments, no '%' wrap.
All of those are supported by grbl 1.1f.

SAFETY
------
G-code is only a suggestion. Verify the program and AIR-CUT IT FIRST, with the
tool clear of the work. Simultaneous 4-axis output has not been proven on a
Genmitsu by anyone yet; 3+1 indexed work is ordinary G94 g-code and lower risk.
No warranty. You are responsible for what the machine does.
"""

from rotatocam.post._emit import render, render_program
from rotatocam.post.base import Post, PostOptions
from rotatocam.toolpath.types import Toolpath

_DIALECT = "Genmitsu (Grbl 1.1f ARM32)"
_ROTARY_LETTER = "A"


class GenmitsuPost(Post):
    controller_key = "genmitsu"
    display_name = "genmitsu"

    def post(self, toolpath: Toolpath, options: PostOptions) -> str:
        return render(toolpath, options, _ROTARY_LETTER, _DIALECT,
                      end_code="M30", wrap_percent=False, comment_style="semicolon")

    def post_program(self, toolpath: Toolpath, spans, options: PostOptions) -> str:
        return render_program(toolpath, spans, options, _ROTARY_LETTER, _DIALECT,
                              end_code="M30", wrap_percent=False, comment_style="semicolon")
