from math import atan2, atanh, degrees, sqrt
from light import *
import ui
from kivy.clock import Clock
from stupidArtnet import StupidArtnet
import argparse

ARTNET : StupidArtnet = None
ARTNET_HZ = 1.

# channels are 1-based in the manual. Here they are 0 based to be offset from base light address
CH_PAN = 0
CH_TILT = 1
CH_COLOR = 2
CH_GOBO = 3
CH_SHUTTER = 4
CH_DIMMER = 5
CH_FOCUS = 6
CH_SPEED = 9

def init_artnet():
    global ARTNET
    target_ip = '192.168.10.222'		# typically in 2.x or 10.x range
    universe = 0										# see docs
    packet_size = 512								# it is not necessary to send whole universe

    ARTNET = StupidArtnet(target_ip, universe, packet_size, 30, True, True)    

def send_dmx(dt):
    for l in LIGHTS:
        ARTNET.set_single_value(l.address + CH_PAN, round(l.pan))
        ARTNET.set_single_value(l.address + CH_TILT, round(l.tilt))
        ARTNET.set_single_value(l.address + CH_COLOR, round(l.color))
        ARTNET.set_single_value(l.address + CH_GOBO, round(l.get_gobo()))
        ARTNET.set_single_value(l.address + CH_SHUTTER, round(l.shutter))
        ARTNET.set_single_value(l.address + CH_DIMMER, round(l.dimmer))
        ARTNET.set_single_value(l.address + CH_FOCUS, round(l.focus))
        #ARTNET.set_single_value(l.address + CH_SPEED, round(l.speed))

    ARTNET.show()
    
    LIGHTS[0].print()
    
    

def load_interp_points(csvname):
    id = []
    points = []
    values = [[],[]]
    with open(csvname) as csvfile:
        r = csv.reader(csvfile)
        for row in r: 
            # skip header row
            if row[0] == "Id" : continue

            #if row[3] == "": continue

            # recreate row, casting columns 1 onwards as floats
            row = [row[0]] + [float(n) if n != '' else 0 for n in row[1:]]
            
            id.append(row[0])
            points.append(row[1:3])
            values[0].append(row[3:5])
            values[1].append(row[5:8])
            #interp_values.append(spos_to_dmx(row[1], row[2]))
    
    return id, points, values

def spos_to_dmx(y, x):
    y = 1.0 - y #convert to right is min, left is max

    y = (6.3 * y) - 2
    x = 3.8 * x

    # print(f'spos: {y} : {x}')

    height = 1.8
    pan = degrees(atan2(y,x))
    tilt = degrees(atan2(sqrt(x**2 + y**2), height))
    
    #print(f'angle: {pan} : {tilt}')

    pan = int(pan / 540.0 * 255.0)

    tilt += 135
    tilt = int(tilt / 270.0 * 255.0)

    # print(f'dmx: {pan} : {tilt}')
    # print('')
    return [pan, tilt]

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('-c', '--config', action="store_true")
    args = parser.parse_args()

    id, points, values = load_interp_points('interp.csv')

    LIGHTS[0].interp = LinearNDInterpolator(points, values[0])
    LIGHTS[1].interp = LinearNDInterpolator(points, values[1])

    if args.config:
        # only used for displaying the config points on the stage image,
        # to help configure the pan,tilt values used for the interpolation
        for idx, _ in enumerate(id):
            ui.POINTS.append(ui.ConfigPoint(id[idx], points[idx][0], points[idx][1]))

    init_artnet()
    send_event = Clock.schedule_interval(send_dmx, 1/ARTNET_HZ)

    ui.LightApp().run()