#!/usr/bin/python

from websocket import create_connection
from threading import Thread
from numpy import sqrt
from delta_machine import *

class LickrListener:

    ws = None
    queue = []
    
    # length of arms
    L = 285 #mm

    # Delta Radius - distance from edge of end effector to point under center of carriage
    DR = 110 #mm

    # distance the head extends below the effector (Length of tongue)
    Hcz = 55
    
    jog_height = 5 #raise or lower 2 cm
    
    
    #pix2mm = 190./125.
    pix2mm = 0.25
    
    down = True
    
    
    def __init__(self):
        pass
    
    def __init__(self, uri):
        self.create_connection(uri)
    
    def create_connection(self, uri):
        self.ws = create_connection(uri)
        self.ws.send("machine")
   

    def run(self):

        while True:
            result = self.ws.recv()
            result = result.split(',')
            result = [ int(x) for x in result ]
            #convert it:
            result = self.translate_coordinates(result)
            if result is not None:
                self.queue.append(result)
    
    def close(self):    
        self.ws.close()
        
    def pop_queue(self):
        if self.queue: #if the queue is not empty:
            return self.queue.pop(0) #TODO: very inefficient, maybe I should consider a different datastructure
        else:
            return None #nothing to return!
            
    def run_in_background(self):
        thread = Thread(target = ll.run)
        thread.start()
        
    def translate_coordinates(self, coords):
    #Translates the coordinates from [x, y, z] to [A, B, C]
        #First step: center them
        

        
        X = coords[0]
        Y = coords[1]
        
        Z = coords[2]
        
        
        Z = Z * self.jog_height #coords[2] is 1 or 0, so this is jog_height or 0


        if Z == 1 and self.down:
            pass
        elif Z < 1 and self.down:
            self.down = False #jog up
        elif Z == 1 and not self.down:
            self.down = True #jog down
        elif Z < 1 and not self.down:
            #return None
            pass
            
        

        
        
        #Now, convert
        X *= self.pix2mm
        Y *= self.pix2mm
        

        

        
        L = self.L
        DR = self.DR
        Hcz = self.Hcz

        # A is the rode on the Y axis, B is 120 degrees clockwise from A, C is 120 degrees clockwise from 
        # X, Y ,Z are the input poin recieved from the user touch on the screen
        Az = sqrt(pow(L, 2) - pow((X - 0), 2) - pow((Y - DR), 2)) + Z - Hcz
        Bz = sqrt(pow(L, 2) - pow((X - DR*sqrt(3)/2), 2) - pow((Y + DR/2),2)) + Z - Hcz
        Cz = sqrt(pow(L, 2) - pow((X + DR*sqrt(3)/2), 2) - pow((Y + DR/2),2)) + Z - Hcz
        
        Az -= (207.91633650269813 * 3.0/4.0)
        Bz -= (207.91633650269813 * 3.0/4.0)
        Cz -= (207.91633650269813 * 3.0/4.0)
        
        print [Az, Bz, Cz]
        
        return [Az, Bz, Cz]

if __name__ == "__main__":
    #TODO: main method here
    
    stages = virtualMachine(persistenceFile = "test.vmp")

	# You can load a new program onto the nodes if you are so inclined. This is currently set to 
	# the path to the 086-005 repository on Nadya's machine. 
	#stages.xyNode.loadProgram('../../../086-005/086-005a.hex')
	
	# This is a widget for setting the potentiometer to set the motor current limit on the nodes.
	# The A4982 has max 2A of current, running the widget will interactively help you set. 
	#stages.xyNode.setMotorCurrent(0.7)

	# This is for how fast the 
    stages.abcNode.setVelocityRequest(8)	
	
	# Some random moves to test with

    
    
    
	
	# Move!
    """
    for move in moves:
        stages.move(move, 0)
        status = stages.aAxisNode.spinStatusRequest()
		# This checks to see if the move is done.
        while status['stepsRemaining'] > 0:
            time.sleep(0.001)
            status = stages.aAxisNode.spinStatusRequest()  
    """  
    
    
    ll = LickrListener("ws://lickr.herokuapp.com:80")
    
    ll.run_in_background()
    
    while True:
        next = ll.pop_queue()

        if(next):

            # translation from queue format to array inverse kinematics
            coords = next
            stages.move(coords, 0)
            
            # TODO: Figure out what the ideal way to poll for finishd status is. 
            # In the xy_plotter example, the xAxisNode is the only one that is polled.
            # Maybe the way the gestalt network works is there is only one output node
            # for status checking?
            statusX = stages.aAxisNode.spinStatusRequest()
            statusY = stages.bAxisNode.spinStatusRequest()
            statusZ = stages.cAxisNode.spinStatusRequest()

            while(statusX['stepsRemaining'] > 0 or statusY['stepsRemaining'] > 0 or statusZ['stepsRemaining'] > 0):
                time.sleep(0.001)
                statusX = stages.aAxisNode.spinStatusRequest()   
                statusY = stages.bAxisNode.spinStatusRequest()
                statusZ = stages.cAxisNode.spinStatusRequest()
