# 3/1/2024
# Credits to cmorley, many thanks!
# Personal touch and Tested by PoolCNC
# this module creates the necesarry HAL pins 
# - for overriding the sliders with analog values
# - for overriding the SLOW/FAST button for linear and angular movent
# - for jogging axis X, Y, Z, A, B, C with digital inputs
# in QtDragon(_hd)
# put/rename the file in YOUR CONFIG/qtvcp/screens/qtdragon/qtdragon_handler.py
# put/rename the file in YOUR CONFIG/qtvcp/screens/qtdragon_hd/qtdragon_hd_handler.py

import sys
import importlib
from qtvcp.core import Path, Qhal, Action
PATH = Path()
QHAL = Qhal()
ACTION = Action()

# get reference to original handler file so we can subclass it
sys.path.insert(0, PATH.SCREENDIR)
module = "{}.{}_handler".format(PATH.BASEPATH,PATH.BASEPATH)
mod = importlib.import_module(module, PATH.SCREENDIR)
sys.path.remove(PATH.SCREENDIR)
HandlerClass = mod.HandlerClass

# return our subclassed handler object
def get_handlers(halcomp, widgets, paths):
    return [UserHandlerClass(halcomp, widgets, paths)]

class UserHandlerClass(HandlerClass):
    print('Custom subclassed handler loaded\n')

    def init_pins(self):
        super().init_pins()
        self.FEED_RATE_ENABLE = 0
        self.SPINDLE_RATE_ENABLE = 0
        self.ANGULAR_JOG_RATE_ENABLE = 0
        self.JOG_RATE_ENABLE = 0
        self.RAPID_RATE_ENABLE = 0

        # generate the pins to connect analog inputs for slider ANGULAR_JOG 
        # for QtDragon_hd
        pin = QHAL.newpin("jog.override-angular.analog-enable", QHAL.HAL_BIT, QHAL.HAL_IN)
        pin.value_changed.connect(lambda s: self._on_analog_enable_changed(s,"ANGULAR_JOG_RATE"))
        pin = QHAL.newpin("jog.override-angular.direct-value", QHAL.HAL_FLOAT, QHAL.HAL_IN)
        pin.value_changed.connect(lambda s: self._on_analog_value_changed(s,"ANGULAR_JOG_RATE"))
        # make a pin to set turtle jog angular
        pin = QHAL.newpin("jog.override-angular.turtle", QHAL.HAL_BIT, QHAL.HAL_IN)
        pin.value_changed.connect(lambda s: self.togle_jog_range_a(s))
        
         # generate the pins to connect analog inputs for slider JOG_RATE  
		 #for QtDragon_hd
        pin = QHAL.newpin("jog.override-linear.analog-enable", QHAL.HAL_BIT, QHAL.HAL_IN)
        pin.value_changed.connect(lambda s: self._on_analog_enable_changed(s,"JOG_RATE"))
        pin = QHAL.newpin("jog.override-linear.direct-value", QHAL.HAL_FLOAT, QHAL.HAL_IN)
        pin.value_changed.connect(lambda s: self._on_analog_value_changed(s,"JOG_RATE"))
        # make a pin to set turtle jog vel
        pin = QHAL.newpin("jog.override-linear.turtle", QHAL.HAL_BIT, QHAL.HAL_IN)
        pin.value_changed.connect(lambda s: self.togle_jog_range_l(s))

		# generate the pins to connect analog inputs for slider FEED_RATE
        pin = QHAL.newpin("feed.override.analog-enable", QHAL.HAL_BIT, QHAL.HAL_IN)
        pin.value_changed.connect(lambda s: self._on_analog_enable_changed(s,"FEED_RATE"))
        pin = QHAL.newpin("feed.override.direct-value", QHAL.HAL_FLOAT, QHAL.HAL_IN)
        pin.value_changed.connect(lambda s: self._on_analog_value_changed(s,"FEED_RATE"))
        
        # generate the pins to connect analog inputs for slider SPINDLE_RATE
        pin = QHAL.newpin("spindle.override.analog-enable", QHAL.HAL_BIT, QHAL.HAL_IN)
        pin.value_changed.connect(lambda s: self._on_analog_enable_changed(s,"SPINDLE_RATE"))
        pin = QHAL.newpin("spindle.override.direct-value", QHAL.HAL_FLOAT, QHAL.HAL_IN)
        pin.value_changed.connect(lambda s: self._on_analog_value_changed(s,"SPINDLE_RATE"))

		# generate the pins to connect analog inputs for slider RAPID_RATE
        pin = QHAL.newpin("rapid.override.analog-enable", QHAL.HAL_BIT, QHAL.HAL_IN)
        pin.value_changed.connect(lambda s: self._on_analog_enable_changed(s,"RAPID_RATE"))
        pin = QHAL.newpin("rapid.override.direct-value", QHAL.HAL_FLOAT, QHAL.HAL_IN)
        pin.value_changed.connect(lambda s: self._on_analog_value_changed(s,"RAPID_RATE"))
        
        # generate the pins to connect analog inputs for slider MAX_VEL_OVERALL
        pin = QHAL.newpin("maxvel.override.analog-enable", QHAL.HAL_BIT, QHAL.HAL_IN)
        pin.value_changed.connect(lambda s: self._on_analog_enable_changed(s,"MAX_VEL_OVERALL"))
        pin = QHAL.newpin("maxvel.override.direct-value", QHAL.HAL_FLOAT, QHAL.HAL_IN)
        pin.value_changed.connect(lambda s: self._on_analog_value_changed(s,"MAX_VEL_OVERALL"))

        # call keyboard jogging function on HAL pin change
        # kb_jog(state, joint number, direction, fast = False, linear = True)

		# jog pins X axis
        pin = QHAL.newpin("jog.axis.x.plus", QHAL.HAL_BIT, QHAL.HAL_IN)
        pin.value_changed.connect(lambda s: self.kb_jog(s, 0, 1, fast = False, linear = True))
        pin = QHAL.newpin("jog.axis.x.minus", QHAL.HAL_BIT, QHAL.HAL_IN)
        pin.value_changed.connect(lambda s: self.kb_jog(s, 0, -1, fast = False, linear = True))

		# jog pins Y axis
        pin = QHAL.newpin("jog.axis.y.plus", QHAL.HAL_BIT, QHAL.HAL_IN)
        pin.value_changed.connect(lambda s: self.kb_jog(s, 1, 1, fast = False, linear = True))
        pin = QHAL.newpin("jog.axis.y.minus", QHAL.HAL_BIT, QHAL.HAL_IN)
        pin.value_changed.connect(lambda s: self.kb_jog(s, 1, -1, fast = False, linear = True))

		# jog pins Z axis
        pin = QHAL.newpin("jog.axis.z.plus", QHAL.HAL_BIT, QHAL.HAL_IN)
        pin.value_changed.connect(lambda s: self.kb_jog(s, 2, 1, fast = False, linear = True))
        pin = QHAL.newpin("jog.axis.z.minus", QHAL.HAL_BIT, QHAL.HAL_IN)
        pin.value_changed.connect(lambda s: self.kb_jog(s, 2, -1, fast = False, linear = True))

        # jog pins A axis
        pin = QHAL.newpin("jog.axis.a.plus", QHAL.HAL_BIT, QHAL.HAL_IN)
        pin.value_changed.connect(lambda s: self.kb_jog(s, 3, 1, fast = False, linear = False))
        pin = QHAL.newpin("jog.axis.a.minus", QHAL.HAL_BIT, QHAL.HAL_IN)
        pin.value_changed.connect(lambda s: self.kb_jog(s, 3, -1, fast = False, linear = False))

        # jog pins B axis
#        pin = QHAL.newpin("jog.axis.b.plus", QHAL.HAL_BIT, QHAL.HAL_IN)
#        pin.value_changed.connect(lambda s: self.kb_jog(s, 4, 1, fast = False, linear = False))
#        pin = QHAL.newpin("jog.axis.b.minus", QHAL.HAL_BIT, QHAL.HAL_IN)
#        pin.value_changed.connect(lambda s: self.kb_jog(s, 4, -1, fast = False, linear = False))

        # jog pins C axis
        pin = QHAL.newpin("jog.axis.c.plus", QHAL.HAL_BIT, QHAL.HAL_IN)
        pin.value_changed.connect(lambda s: self.kb_jog(s, 5, 1, fast = False, linear = False))
        pin = QHAL.newpin("jog.axis.c.minus", QHAL.HAL_BIT, QHAL.HAL_IN)
        pin.value_changed.connect(lambda s: self.kb_jog(s, 5, -1, fast = False, linear = False))
		
	    
    def togle_jog_range_l(self, state):
        self.w.btn_jog_l_slow.setChecked(state)
        self.w.btn_jog_l_slow.clicked.emit(state)

    def togle_jog_range_a(self, state):
        self.w.btn_jog_a_slow.setChecked(state)
        self.w.btn_jog_a_slow.clicked.emit(state)
        # to invert the state:
        #self.w.btn_jog_a_slow.setChecked(not state)
        #self.w.btn_jog_a_slow.clicked.emit(not state)

    def _on_analog_enable_changed(self, state, command):
        self['{}_ENABLE'.format(command)] = state

    def _on_analog_value_changed(self, value, command):
        #print(value,command,self['{}_ENABLE'.format(command)])
        if self['{}_ENABLE'.format(command)]:
            if command == 'JOG_RATE':
                #print(value,command,self.w.slider_jog_linear.maximum(),self.w.slider_jog_linear.minimum() )
                self.w.slider_jog_linear.setValue(self.w.slider_jog_linear.minimum()+(self.w.slider_jog_linear.maximum()-self.w.slider_jog_linear.minimum())*value)                
            elif command == 'ANGULAR_JOG_RATE':
                #print(value, command, self.w.slider_jog_angular.maximum(), self.w.slider_jog_angular.minimum())
                self.w.slider_jog_angular.setValue(self.w.slider_jog_angular.minimum()+(self.w.slider_jog_angular.maximum()-self.w.slider_jog_angular.minimum())*value)
            elif command == "FEED_RATE":
                #print(value,command,self.w.slider_feed_ovr.maximum(),self.w.slider_feed_ovr.minimum() )
                self.w.slider_feed_ovr.setValue(self.w.slider_feed_ovr.minimum()+(self.w.slider_feed_ovr.maximum()-self.w.slider_feed_ovr.minimum())*value)
            elif command == "SPINDLE_RATE":
                #print(value,command,self.w.slider_spindle_ovr.maximum(),self.w.slider_spindle_ovr.minimum() )
                self.w.slider_spindle_ovr.setValue(self.w.slider_spindle_ovr.minimum()+(self.w.slider_spindle_ovr.maximum()-self.w.slider_spindle_ovr.minimum())*value)
            elif command == "RAPID_RATE":
                #print(value,command,self.w.slider_rapid_ovr.maximum(),self.w.slider_rapid_ovr.minimum() )
                self.w.slider_rapid_ovr.setValue(self.w.slider_rapid_ovr.minimum()+(self.w.slider_rapid_ovr.maximum()-self.w.slider_rapid_ovr.minimum())*value)
            elif command == "MAX_VEL_OVERALL":
                #print(value,command,self.w.slider_maxv.maximum(),self.w.slider_maxv_ovr.minimum() )
                self.w.slider_maxv.setValue(self.w.slider_maxv.minimum()+(self.w._maxv.maximum()-self.w.slider_rapid_ovr.minimum())*value)                  
            else:
                ACTION['SET_{}'.format(command)](value*100)


