#! /usr/bin/python

import sys, os
import traceback
from math import sin,cos

from interpreter import *
import emccanon
from util import lineno, call_pydevd
#from configparser import ConfigParser
import linuxcnc, hal
#from stdglue import *
# raises InterpreterException if execute() or read() fails
throw_exceptions = 1

def queuebuster(self, **words):
    yield INTERP_EXECUTE_FINISH
    
def M6_remap(self, **words):
    #--------------------------------------------------
    # if in preview mode exit without doing anything and all ok
    #----------------------------------------------------------
    if self.task==0:
        return INTERP_OK
        
    change_prolog1(self, **words)
    """
    if self.selected_pocket < 0:
        return "M6: no tool prepared"

    if self.cutter_comp_side:
        return "Cannot change tools with cutter radius compensation on"

    self.params["tool_in_spindle"] = self.current_tool
    self.params["selected_tool"] = self.selected_tool
    self.params["current_pocket"] = self.current_pocket
    self.params["selected_pocket"] = self.selected_pocket
    """
    #self.execute("G53 G0 Z0.0",lineno())
    #INTERP_EXECUTE_FINISH
    #print("Moved to Z = 0.0")
    #return INTERP_OK
    try:
        # stop readhead to ensure correct data
        #emccanon.WAIT(10, 1, 3, 0.01)
        #yield INTERP_EXECUTE_FINISH
        #emccanon.GET_EXTERNAL_DIGITAL_INPUT(10, 1)
        
        # read and remember coordinates in the begining of the operation
        self.x_init = round(emccanon.GET_EXTERNAL_POSITION_X(), 3)
        self.y_init = round(emccanon.GET_EXTERNAL_POSITION_Y(), 3)
        self.z_init = round(emccanon.GET_EXTERNAL_POSITION_Z(), 3)

        
        # check the spindle state and stop it if needed;
        self.spindle_speed = emccanon.GET_EXTERNAL_SPEED(0)
        if self.spindle_speed:
            #emccanon.SET_SPINDLE_SPEED(0, 0)
            StopSpindleNow(self)
        if self.params[5399] < 0:
            msg = "Spindle has not stopped even after M66"
            self.set_errormsg(msg)
            return ReturnERROR()
            
        #-----------------------
        # raise the Z
        #-----------------------
        #MoveZtoZero(self)
        self.execute("G53 G0 Z0.0",lineno())
        #yield INTERP_EXECUTE_FINISH
        print("Moved to Z = 0.0")
        #----------------------------------------------
        
        #process_file = '/home/cnc/HALO/config/config-inc/process.inc'
        #self.config_process = ConfigParser()
        #self.config_process.optionxform = str
        #self.config_process.read(process_file)
        self.i = linuxcnc.ini(os.environ['INI_FILE_NAME'])
        #print(os.environ['INI_FILE_NAME'])
        self.params['xy_speed'] = float(self.i.find('POCKETS','XYSPEED'))
        self.params['z_speed'] = float(self.i.find('POCKETS','ZSPEED'))
        if int(self.current_pocket) > 0:
            print('setting up drop off pocket')
            self.params['cp_x_out'] = float(self.i.find('POCKETS','X{}OUT'.format(self.current_pocket))) or 0
            self.params['cp_y_out'] = float(self.i.find('POCKETS','Y{}OUT'.format(self.current_pocket))) or 0
            self.params['cp_z_out'] = float(self.i.find('POCKETS','Z{}OUT'.format(self.current_pocket))) or 0
            self.params['cp_x_in'] = float(self.i.find('POCKETS','X{}IN'.format(self.current_pocket))) or 0
            self.params['cp_y_in'] = float(self.i.find('POCKETS','Y{}IN'.format(self.current_pocket))) or 0
            self.params['cp_z_in'] = float(self.i.find('POCKETS','Z{}IN'.format(self.current_pocket))) or 0
            if self.params['cp_x_out'] == 0 or self.params['cp_y_out'] == 0 or self.params['cp_z_out'] == 0 or\
               self.params['cp_x_in'] == 0 or self.params['cp_y_in'] == 0 or self.params['cp_z_in'] == 0:
                msg = "invalid pocket parameters for current tool"
                self.set_errormsg(msg)
                return ReturnERROR()
            # drop off current tool here
            DropTool(self)
            
        if int(self.selected_pocket) > 0:
            print('setting up pick up pocket')
            self.params['sp_x_out'] = float(self.i.find('POCKETS','X{}OUT'.format(self.selected_pocket))) or 0
            self.params['sp_y_out'] = float(self.i.find('POCKETS','Y{}OUT'.format(self.selected_pocket))) or 0
            self.params['sp_z_out'] = float(self.i.find('POCKETS','Z{}OUT'.format(self.selected_pocket))) or 0
            self.params['sp_x_in'] = float(self.i.find('POCKETS','X{}IN'.format(self.selected_pocket))) or 0
            self.params['sp_y_in'] = float(self.i.find('POCKETS','Y{}IN'.format(self.selected_pocket))) or 0
            self.params['sp_z_in'] = float(self.i.find('POCKETS','Z{}IN'.format(self.selected_pocket))) or 0
            if self.params['sp_x_out'] == 0 or self.params['sp_y_out'] == 0 or self.params['sp_z_out'] == 0 or\
               self.params['sp_x_in'] == 0 or self.params['sp_y_in'] == 0 or self.params['sp_z_in'] == 0:
                msg = "invalid pocket parameters for selected tool"
                self.set_errormsg(msg)
                return ReturnERROR()
            # pick up new tool here
            GetTool(self)
    
    # end your subroutine with
    #-----------------------------------------
    # We have errors ! catch and return error
    #-----------------------------------------
    except InterpreterException,e:
        msg = "BOB look at this error : %d: '%s' - %s" % (e.line_number,e.line_text, e.error_message)
        self.set_errormsg(msg) # replace builtin error message
        print("%s" % msg)
        return ReturnERROR()

    except IOError as e:
        print "I/O error({0}): {1}".format(e.errno, e.strerror)
        return ReturnERROR()
    except ValueError:
        print "Could not convert data to an integer."
        return ReturnERROR()
    except ZeroDivisionError as detail:
        print 'Handling run-time error:', detail
        return ReturnERROR()
    except:
        print "Unexpected error:", sys.exc_info()[0]
        raise
   
    finally:
        print 'Hold on, off to epilog coming up!'
        print("Current pocket = %s" % self.current_pocket)
        print("Selected pocket = %s" % self.selected_pocket)
        print("Param.Selected pocket = %s" % int(self.params["selected_pocket"]))
        print("Current tool in spindle = %s" % self.current_tool)
        print("Selected tool = %s" % self.selected_tool)
        
        self.return_value = self.selected_tool
    #-----------------------
    # all fine, return ok !
    #-----------------------
        # This is the change_epilog within remap body     
        print("Self return value = %s" % self.return_value)
        print('Doing epilog')
        #print("Current pocket = %s" % self.current_pocket)
        #print("Selected pocket = %s" % self.selected_pocket)
        #print("Param.Selected pocket = %s" % int(self.params["selected_pocket"]))
        #print("Current tool in spindle = %s" % self.current_tool)
        #print("Selected tool = %s" % self.selected_tool)
        self.selected_pocket =  int(self.params["selected_pocket"])
        print("before emccannon CHANGE TOOL")
        emccanon.CHANGE_TOOL(self.selected_pocket)
        print("emccannon CHANGE TOOL sent")
        self.current_pocket = self.selected_pocket
        #self.selected_pocket = -1
        #self.selected_tool = -1
        # cause a sync()
        print("Syncing tool parameter")
        self.set_tool_parameters()
        self.toolchange_flag = True
        print('Completed epilog')
        print("Current pocket = %s" % self.current_pocket)
        print("Selected pocket = %s" % self.selected_pocket)
        print("Param.Selected pocket = %s" % int(self.params["selected_pocket"]))
        print("Current tool in spindle = %s" % self.current_tool)
        print("Selected tool = %s" % self.selected_tool)
        
    return INTERP_OK
    
#----------------------------------------------------------
def DropTool(self):
    print('moving to front of current tool pocket')
    self.execute('G53 G0 X%f Y%f' % (self.params['cp_x_out'], self.params['cp_y_out']))
    self.execute('G53 G0 Z%f' % (self.params['cp_z_out']))
    print('moving into current tool pocket')
    self.execute('G53 G1 X%f Y%f Z%f F%f' % (self.params['cp_x_in'], self.params['cp_y_in'], self.params['cp_z_in'], self.params['xy_speed']))
    # open collet
    print('opening collet')
    self.execute('M64 P0')
    # check if collet open
    self.execute('M66 P0 L3 Q3')
    #INTERP_EXECUTE_FINISH
    if self.params[5399] < 0:
        msg = 'collet failed to open - toolchange aborted'
        self.set_errormsg(msg)
        return ReturnERROR()
    # move up if tool released
    print('collet released, moving up')
    self.execute('G53 G0 Z0')
    # turn off tool release signal
    print('closing collet')
    self.execute('M65 P0')
    #yield INTERP_EXECUTE_FINISH
#----------------------------------------------------------
def GetTool(self):
    self.execute('G53 G0 Z0')
    self.execute('G53 G0 X%f Y%f' % (self.params['sp_x_in'], self.params['sp_y_in']))
    # open collet
    self.execute('M64 P0')
    # check if collet open
    self.execute('M66 P0 L3 Q3')
    #INTERP_EXECUTE_FINISH
    if self.params[5399] < 0:
        msg = 'collet failed to open'
        self.set_errormsg(msg)
        return ReturnERROR()
    # move down onto tool
    self.execute('G53 G1 Z%d F%d' % (self.params['sp_z_in'], self.params['z_speed']))
    # close collet
    self.execute('M65 P0')
    # wait for collet to close
    self.execute('M66 P0 L4 Q3')
    if self.params[5399] < 0:
        msg = 'collet failed to close - toolchange aborted'
        self.set_errormsg(msg)
        return ReturnERROR()
    # move out of pocket
    self.execute('G53 G1 X%d Y%d Z%d F%f' % (self.params['sp_x_out'], self.params['sp_y_out'], self.params['sp_z_out'], self.params['xy_speed']))
    self.execute('G0 Z0')
    #yield INTERP_EXECUTE_FINISH
#----------------------------------------------------------
def MoveZtoZero(self):
    self.execute("G53 G0 Z0.0",lineno())
    #yield INTERP_EXECUTE_FINISH
    print("Moved to Z = 0.0")
#----------------------------------------------------------
def StopSpindleNow(self):
    self.execute("M5", lineno())
    self.execute("M66 P2 L3 Q15")
    #yield INTERP_EXECUTE_FINISH
    print("Stop Spindle command sent")
#---------------------------------------------------------------------------------------
# ReturnOK()
#---------------------------------------------------------------------------------------    
def ReturnOK():
    print("Calling DoYield()")
    DoYield()
    print("After DoYield(), before return INTERP_OK")
    return INTERP_OK
#---------------------------------------------------------------------------------------
# ReturnERROR()
#---------------------------------------------------------------------------------------
def ReturnERROR():
    # if DoYield() is needed but I think not
    #DoYield()
    print("Before return INTERP_ERROR")
    return INTERP_ERROR
    
#----------------------------------------------------------
#----------------------------------------------------------
def change_prolog1(self, **words):
    try:
        if self.selected_pocket < 0:
            return "M6: no tool prepared"

        if self.cutter_comp_side:
            return "Cannot change tools with cutter radius compensation on"

        self.params["tool_in_spindle"] = self.current_tool
        self.params["selected_tool"] = self.selected_tool
        self.params["current_pocket"] = self.current_pocket
        self.params["selected_pocket"] = self.selected_pocket
        
        return INTERP_OK
    except Exception, e:
        return "M6/change_prolog: %s" % (e)

def change_epilog(self, **words):
    try:
            #print("Change epilog executing....")
            if self.return_value > 0.0:
                print("pass return value")
                self.selected_pocket =  int(self.params["selected_pocket"])
                print("before emccannon CHANGE TOOL")
                emccanon.CHANGE_TOOL(self.selected_pocket)
                print("emccannon CHANGE TOOL sent")
                self.current_pocket = self.selected_pocket
                self.selected_pocket = -1
                self.selected_tool = -1
                # cause a sync()
                print("Syncing tool parameters now")
                self.set_tool_parameters()
                self.toolchange_flag = True
                yield INTERP_EXECUTE_FINISH
            else:
                self.set_errormsg("M6 aborted (return code %.1f)" % (self.return_value))
                return
    except Exception, e:
        self.set_errormsg("M6/change_epilog: %s" % (e))
        return 

