import gpio
import leds
import utime
import display
import color
import buttons
import vibra


# Change the starting player parameter two false
# on the other board.
start_player = True

pin_tx = gpio.WRISTBAND_3
pin_rx = gpio.WRISTBAND_4
led_recv = leds.BOTTOM_RIGHT
led_send = leds.BOTTOM_LEFT

baud = 0.01  # not really but more time length of one bit

disp = display.open()
disp.print('niotacin', posx=20, fg=color.COMMYELLOW)
disp.print('pmaC', fg=color.CAMPGREEN, posy=20)
disp.update()

# buffer for received bits
recvd = []

# position, velocity of the player.
# delay between led updates.
pos, vel, delay_ms = 0, 0, 255

gpio.set_mode(pin_rx, gpio.mode.INPUT | gpio.mode.PULL_UP)

def tx_on():
    leds.set(led_send, color.CAMPGREEN)
    gpio.set_mode(pin_tx, gpio.mode.OUTPUT)
    gpio.write(pin_tx, False)

def tx_off():
    leds.set(led_send, color.BLACK)
    gpio.set_mode(pin_tx, gpio.mode.INPUT)

def check_tx():
    return gpio.get_mode(pin_tx) == gpio.mode.OUTPUT

def check_rx():
    val = gpio.read(pin_rx) == 0
    leds.set(led_recv, color.CAMPGREEN if val else color.BLACK)
    return val

def display_input_buffer():
    'Currently no used but good for debugging.'
    global disp, recvd

    disp.clear()
    s = ''
    for i in recvd:
        s += str(i)
    disp.print(s)

    disp.print(str(recvd_int()), posy=20)
    leds.set(0, [i,0,0])

    disp.update()

def startbit_found():
    return check_rx()

def receive_byte():
    global recvd

    utime.sleep(0.5 * baud) # waiting for databits

    recvd = []
    for _ in range(8):
        utime.sleep(baud)
        if check_rx():
            recvd.append(1)
        else:
            recvd.append(0)

    utime.sleep(baud)  # waiting for stopbit
    leds.set(led_recv, color.BLACK)

def recvd_int():
    'Convert the bits in the buffer into a byte.'
    s = ''
    for i in recvd:
        s += str(i)

    return int('0b'+s, 2)

def tx_byte(byte):
    tx_on() # Startbit
    utime.sleep(baud)
    for x in range(7,-1,-1):
        if (byte & (1<<x)) == (1<<x):
            tx_on()
        else:
            tx_off()
        utime.sleep(baud)
    tx_off() # Stopbit
    utime.sleep(5*baud)

def handle_input():
    global vel, delay_ms
    
    if buttons.read(buttons.BOTTOM_LEFT) != 0 and pos >= 8 and vel > 0:
        vel = -vel
        if pos == 8: delay_ms = delay_ms
        elif pos == 9: delay_ms = int(delay_ms * 0.5)

def start_game(starting_player):
    global pos, vel, delay_ms

    width = 11 # leds
    if starting_player:
        pos, vel = width - 1, -1
    else:
        # pos=-1 indicating the ball is on the other board.
        pos, vel = -1, 0

    col = color.CAMPGREEN
    while True:
        handle_input()
        #print('pos vel', pos, vel)
        pos += vel
        if pos < 0 and vel != 0:
            tx_byte(delay_ms)
            pos, vel = -1, 0
        if pos >= width - 1:
            vel = -vel
            vibra.vibrate(60)
        
        # await
        if startbit_found():
            receive_byte()
            delay_ms = recvd_int()
            pos, vel = 0, 1

        # draw
        leds.clear()
        if pos >= 0:
            leds.set(pos, col)
            utime.sleep_ms(delay_ms)


tx_off()

start_game(starting_player=start_player)