# -*- coding: utf-8 -*-
"""

Copyright 2012 Lars Kruse <devel@sumpfralle.de>

This file is part of pyMKcam.

pyMKcam is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

pyMKcam is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with pyMKcam.  If not, see <http://www.gnu.org/licenses/>.
"""

import os
import pymkcam.Exporters.GCode
from pymkcam.Toolpath import CORNER_STYLE_EXACT_PATH, CORNER_STYLE_EXACT_STOP, \
        CORNER_STYLE_OPTIMIZE_SPEED, CORNER_STYLE_OPTIMIZE_TOLERANCE



DEFAULT_HEADER = (
                ("M453", "make sure machine is in CNC mode"),
                ("M82", "select absolute coordinate system"),
                )


DEFAULT_FOOTER = (
            #("G0 Z5.00000 F200", "safe Z position"),
            #("M5", "stop spindle"),
            ("M18", "unlock all steppers"),
            ("M2", "program ends")
      )

DEFAULT_DIGITS = 6

def _render_number(number):
    if int(number) == number:
        return "%d" % number
    else:
        return ("%%.%df" % DEFAULT_DIGITS) % number


class MK4duo(pymkcam.Exporters.GCode.BaseGenerator):

    sspeed = "10000"
    feed = "300"
    fast = "3000"

    def add_header(self):
        for command, comment in DEFAULT_HEADER:
            self.add_command(command, comment=comment)
        if True:
            self.add_command("G21", "metric")
        else:
            self.add_command("G20", "imperial")
        self.header_added = True

    def add_footer(self):
        for command, comment in DEFAULT_FOOTER:
           self.add_command(command, comment=comment)

    def add_comment(self, comment):
        self.add_command("; %s" % comment)

    def add_command(self, command, comment=None):
        if comment:
            self.add_comment(comment)
        self.destination.write(command)
        self.destination.write(os.linesep)

    def add_move(self, coordinates, is_rapid=False):
        components = []
        # the cached value may be:
        #   True: the last move was G0
        #   False: the last move was G1
        #   None: some non-move happened before
        components.append("G0" if is_rapid else "G1")
        axes = [axis for axis in "XYZABCUVW"]
        previous = self._get_cache("position", [None] * len(coordinates))
        for (axis, value, last) in zip(axes, coordinates, previous):
            if (last is None) or (last != value):
                components.append("%s%.6f" % (axis, value))
        if len(components) > 1:
            if self._get_cache("rapid_move", None) != is_rapid:
                components.append("F%s" % (self.fast if is_rapid else self.feed)) 
            command = " ".join(components)
            if command.strip():
                self.add_command(command)

    def command_feedrate(self, feedrate):
        self.feed = _render_number(feedrate)

    def command_select_tool(self, tool_id):
        if self._last_tool_id > 0 and self._last_tool_id != tool_id:
            self.add_command("T%d" % tool_id, "select tool")
        self._last_tool_id = tool_id

    def command_spindle_speed(self, speed):
        self.sspeed = _render_number(speed)

    def command_spindle_enabled(self, state):
        if state:
            self.add_command("M3 S%s" % self.sspeed, "start spindle")
        else:
            self.add_command("M5", "stop spindle")

    def command_delay(self, seconds):
        self.add_command("G04 S%d" % seconds, "wait for %d seconds" % seconds)

    def command_corner_style(self,
            (path_mode, motion_tolerance, naive_tolerance)):
        if path_mode == CORNER_STYLE_EXACT_PATH:
            self.add_comment("G61 exact path mode was requested but not implemented")
        elif path_mode == CORNER_STYLE_EXACT_STOP:
            self.add_comment("G61.1 exact stop mode was requested but not implemented")
        elif path_mode == CORNER_STYLE_OPTIMIZE_SPEED:
            self.add_comment("G64 continuous mode with maximum speed was requested but not implemented")
        else:
            if not naive_tolerance:
                self.add_comment("G64 P%f continuous mode with tolerance was requested but not implemented" % motion_tolerance)
            else:
                self.add_command("G64 P%f Q%f continuous mode with tolerance and cleanup was requested but not implemented" % \
                        (motion_tolerance, naive_tolerance))

