#!/usr/bin/env python
# coding: utf-8

# In[12]:


import requests as rq
import sys
import time
import binascii
import numpy as np
rq.packages.urllib3.connection.HTTPConnection.default_socket_options = [(6,3,1)]


# In[24]:


global position
address=32
#path = "/golem/database/www/plot_app/plot_app/"
path = "/tmp/" #Prozatim pro Vojtu 1222
position = int(np.loadtxt(f'rad_position')) # -1 mm

homing_position = 134 # mm was 125
DISTANCE_TO_CENTER = 315 #mm
MAXIMUM_DISTANCE_FROM_CENTER = 181 # mm # RP was 190 mm (vzdalenost od priruby k sonde)

max_moves = 3

def post(index,subindex,value):
        rq.post(f'http://192.168.2.{address}/od/{index}/{subindex}',data=f'{value}',
                    headers={'Content-Type': 'application/x-www-form-urlencoded'})
        time.sleep(0.001)


def get(index,subindex,show):
        output = rq.get(f'http://192.168.2.{address}/od/{index}/{subindex}').text
        if(show==True):
            print(f'object: {index}:{subindex}-------------')
            print('hexadec: '+ str(output))
            print('decimal:' + str(int(output[1:-1],16)))
            print('binary: '+ str(bin(int(output[1:-1], 16))[2:]))
        time.sleep(0.001)
        return output


def inic():
    post("2030","00",'"000000C8"') # radialni ma 000000C8
    time.sleep(0.01)
    post("2031","00",'"000003E8"')
    time.sleep(0.01)
    post("6075","00",'"000001F4"')
    time.sleep(0.01)
    post("3202","00",'"00000008"')
    time.sleep(0.01)


def homing_rad():
    global position
    position = -1
    inic()
    time.sleep(0.1)

    post("60FE","01",'"00000000"')              # brake off
    time.sleep(0.1)
    post("6060","00",'"03"')
    time.sleep(0.1)
    post("6042","00",'"00F0"')  #target speed
    time.sleep(0.1)
    post("606D","00",'"0010"')  # velocity window
    time.sleep(0.1)
    post("606E","00",'"0010"')  # time window
    time.sleep(0.1)
    post("60FF","00",'"00000010"') # this speed is OK for radial one for profile velocity mode
    time.sleep(0.1)

    post("607E","00",'"00"')    #polarity
    time.sleep(0.1)

    post("6040","00",'"0006"')
    time.sleep(0.1)
    post("6040","00",'"0007"')
    time.sleep(0.1)
    post("6040","00",'"000F"')
    time.sleep(0.5)

    while(True):
        time.sleep(0.01)
        if(get('60FD','00',False) == '"00040000"'):
            #print('ON')
            post("6040","00",'"0000"')                  # turn everything off
            time.sleep(0.01)
            post("60FE","01",'"00000001"')              # brake on
            time.sleep(0.01)
            post("6040","00",'"0080"') # remove error
            break
    return position


def shut_down():
    inic()
    post("6040","00",'"0000"')                  # turn everything off
    post("60FE","01",'"00000001"')              # brake on
    post("6040","00",'"0080"') # remove error


def get_time(r):
    return (r-2.002)/2.137


def set_r(t,v,pol):
    inic()
    time.sleep(0.1)

    post("60FE","01",'"00000000"')              # brake off
    time.sleep(0.1)
    post("6060","00",'"03"')
    time.sleep(0.1)
    post("6042","00",'"00F0"')  #target speed
    time.sleep(0.1)
    post("606D","00",'"0010"')  # velocity window
    time.sleep(0.1)
    post("606E","00",'"0010"')  # time window
    time.sleep(0.1)
    post("60FF","00",v) # '"00000010"' this speed is OK for radial one for profile velocity mode
    time.sleep(0.1)

    if(pol=='in'):
        post("607E","00",'"40"')
    if(pol=='out'):
        post("607E","00",'"00"')    #polarity

    time.sleep(0.1)

    post("6040","00",'"0006"')
    time.sleep(0.1)
    get("6041","00",False)
    post("6040","00",'"0007"')
    time.sleep(0.1)
    post("6040","00",'"000F"')
    time.sleep(0.5)
    time.sleep(t)
    #print('ON')
    post("6040","00",'"0000"')                  # turn everything off
    time.sleep(0.01)
    post("60FE","01",'"00000001"')              # brake on
    time.sleep(0.01)
    post("6040","00",'"0080"') # remove error


def shift_1mm(direction):
    inic()
    set_r(6.5,'"00000001"',direction) # was 6
    global position
    if(direction == 'in'):
        position +=1
    if(direction == 'out'):
        position -=1
    return position

def shift_2mm(direction):
    inic()
    set_r(6.7,'"00000002"',direction) # was 6.25
    global position
    if(direction == 'in'):
        position +=2
    if(direction == 'out'):
        position -=2
    return position

def shift_5mm(direction):
    inic()
    set_r(3.95,'"00000008"',direction) # was 3.5
    global position
    if(direction == 'in'):
        position +=5
    if(direction == 'out'):
        position -=5
    return position


def major_shift(r, direction, estm):
    inic()
    set_r(get_time(r),'"00000010"',direction)
    global position
    position = estm
    return position

def shut_down():
    inic()
    post("6040","00",'"0000"')                  # turn everything off
    post("60FE","01",'"00000001"')              # brake on
    post("6040","00",'"0080"') # remove error



def shift_to(desired_loc):
    global position
    if not type(desired_loc) is int:
        raise TypeError("Only integers are allowed")

    if(25 > desired_loc or desired_loc > 125):
        raise Exception('desired location out of bounds')
    estm = DISTANCE_TO_CENTER - (MAXIMUM_DISTANCE_FROM_CENTER + desired_loc)
    shift = abs((DISTANCE_TO_CENTER - (MAXIMUM_DISTANCE_FROM_CENTER + desired_loc)) - position)
    direction = ''
    if estm - position > 0:
        direction = 'in'
    elif estm - position < 0:
        direction = 'out'

    else:
        print('desired location is the same as current estimated location')

    if shift >= 10 and shift <= 100:
        return major_shift(shift, direction, estm)

    elif shift == 9:
            shift_5mm(direction)
            shift_2mm(direction)
            return shift_2mm(direction)
    elif shift == 8:
            shift_5mm(direction)
            shift_2mm(direction)
            return shift_1mm(direction)
    elif shift == 7:
            shift_5mm(direction)
            return shift_2mm(direction)
    elif shift == 6:
            shift_5mm(direction)
            return shift_1mm(direction)
    elif shift == 5:
            return shift_5mm(direction)
    elif shift == 4:
            shift_2mm(direction)
            return shift_2mm(direction)
    elif shift == 3:
            shift_2mm(direction)
            return shift_1mm(direction)
    elif shift == 2:
            return shift_2mm(direction)
    elif shift == 1:
            return shift_1mm(direction)
    elif shift == 0:
            return position


# In[26]:

if(np.size(sys.argv) == 2):
    if(sys.argv[1] == 'wake'):
        try:
            inic()
            homing_rad()
            shut_down()
        except Exception as e:
            print(e)

    elif(sys.argv[1] == 'sleep'):
        try:
            inic()
            homing_rad()
            shut_down()
            f =  open(f'rad_position', 'w+')
            f.write(f'{position}')
            f.close
        except Exception as e:
            print(e)

    elif(sys.argv[1] == 'home'):
        try:
            inic()
            homing_rad()
            shut_down()
            f = open('rad_position', 'w+')
            f.write(f'{position}')
            f.close()
            moves_file = open('number_of_moves', 'w+')
            moves_file.write(str(0))
            moves_file.close()
        except Exception as e:
            print(e)

    else:
        try:
            requestedPosition = int(sys.argv[1])
            if( homing_position-120 <  requestedPosition < homing_position+20 ):  # was 25 < requestedPosition < 125, 100 is range of the manipulator
                try:
                    inic()
                    moves_file = open('number_of_moves', 'r')
                    number_of_moves = int(moves_file.readline().strip('\n'))
                    moves_file.close()
                    if(number_of_moves >= max_moves):
                         homing_rad()
                         moves_file = open('number_of_moves','w+')
                         moves_file.write('0')
                         moves_file.close()
                    else:
                         moves_file = open('number_of_moves','w+')
                         moves_file.write(str(number_of_moves+1))
                         moves_file.close()
                    shut_down()
                    position = shift_to(int(sys.argv[1]))
                    f =  open(f'rad_position', 'w+')
                    f.write(f'{position}')
                    f.close
                    shut_down()
                except Exception as e:
                    print(e)
            else:
                print('requested probe position out of bounds')
        except Exception  as e:
                print('not integer, ', e)
        #print("something were wrong with manipulator")
else:
    print('wrong number of inputs')

