# light jar
# BLE Client Code

import board
import time
import neopixel
from adafruit_pixel_framebuf import PixelFramebuffer
from adafruit_pixel_framebuf import VERTICAL
import digitalio
import adafruit_lis3dh
import busio
import math
from adafruit_ble import BLERadio
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble.services.nordic import UARTService

from adafruit_bluefruit_connect.packet import Packet
# Only the packet classes that are imported will be known to Packet.
from adafruit_bluefruit_connect.color_packet import ColorPacket


AQUA = (0, 255, 255)
GOLD = (255, 255, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)

# Defining Global Variables ========================
# ==================================================
volume = 8.0 # total valume of the cup, double range 0-8
# current Color values
currentR = 0
currentG = 255
currentB = 255

#setup Bluetooth
ble = BLERadio()
uart = UARTService()
advertisement = ProvideServicesAdvertisement(uart)


# initializers =====================================
# ==================================================
pixel_pin = board.A1
pixel_width = 22
pixel_height = 8

pixels = neopixel.NeoPixel(
    pixel_pin,
    pixel_width * pixel_height,
    brightness=0.1,
    auto_write=False,
)

pixel_framebuf = PixelFramebuffer(
    pixels,
    pixel_height,
    pixel_width,
    alternating=True,
    #orientation=VERTICAL,
    #reverse_y=True,
    reverse_x=True,
    rotation=1
)

# initializing accrometer
i2c = busio.I2C(board.ACCELEROMETER_SCL, board.ACCELEROMETER_SDA)
int1 = digitalio.DigitalInOut(board.ACCELEROMETER_INTERRUPT)
accelerometer = adafruit_lis3dh.LIS3DH_I2C(i2c, address=0x19)
accelerometer.range = adafruit_lis3dh.RANGE_8_G

# initializing buttons
button_R = digitalio.DigitalInOut(board.A4)
button_R.switch_to_input(pull=digitalio.Pull.DOWN)

button_G = digitalio.DigitalInOut(board.A5)
button_G.switch_to_input(pull=digitalio.Pull.DOWN)

button_B = digitalio.DigitalInOut(board.A6)
button_B.switch_to_input(pull=digitalio.Pull.DOWN)

# functions ========================================
# ==================================================

# This function converts RGB tuples into nexadecimal
def rgbTOhex(color):
    return int('0x%02x%02x%02x' % color)

# this function updates global variable colors
def cup_setColor(color):
    global currentR
    global currentG
    global currentB
    currentR = color[0]
    currentG = color[1]
    currentB = color[2]

# this function set correct display for the cup
def cup_display():
    global volume
    # first erase all colors
    pixel_framebuf.fill(0x000000)
    # acquire accelerometer readings
    x, y, z = accelerometer.acceleration
    # calculating length of the vector
    length = math.sqrt(x**2+y**2)
    angleIndex = 0

    if x == 0:
        x += 0.001

    angle = math.degrees(math.atan(abs(y)/abs(x)))

    if x<0 and y>0:
        angle = 180 - angle
    elif x<0 and y<0:
        angle = 180 + angle
    elif x>0 and y<0:
        angle = 360 - angle

    angleIndex = int(pixel_width * angle / 360)
    offset = pixel_width/2
    angleIndex = int(angleIndex + offset)%pixel_width

    #print(7-volume-length)

    for i in range(int(pixel_width/2)):
        #if volume != -2:
        pixel_framebuf.line((angleIndex+i)%pixel_width, 8, (angleIndex+i)%pixel_width, int(8-volume-volume/(volume+0.01)*length+(2*length*i/(pixel_width/2))),
                            rgbTOhex((currentR, currentG, currentB)))
        pixel_framebuf.line((angleIndex-i)%pixel_width, 8, (angleIndex-i)%pixel_width, int(8-volume-volume/(volume+0.01)*length+(2*length*i/(pixel_width/2))),
                            rgbTOhex((currentR, currentG, currentB)))

    if 7-volume-length < 0:
        if volume > 0:
            volume = volume - 0.25
        else:
            cup_setColor(BLACK)
    #if length > 7:
        #volume = 0


    # pixel_framebuf.fill(rgbTOhex((currentR, currentG, currentB)))
    # pixel_framebuf.line(angleIndex, 0, angleIndex, 7, 0xFF0000)
    pixel_framebuf.display()


# Main Loop ========================================
# ==================================================
while True:
    pass
    # Advertise when not connected.
    ble.start_advertising(advertisement)
    while not ble.connected:
        pass

    while ble.connected:
        try:
            packet = Packet.from_stream(uart)
            if isinstance(packet, ColorPacket):
                print(packet.color)
                if packet.color[0]!=0 or packet.color[1]!=0 or packet.color[2]!=0:
                    if volume < 8:
                        volume += 0.25
                    currentR = volume/8*currentR + 0.25/8*packet.color[0]
                    currentG = volume/8*currentG + 0.25/8*packet.color[1]
                    currentB = volume/8*currentB + 0.25/8*packet.color[2]
        except ValueError:
            print("valueError")
        if button_R.value:
            if volume < 8:
                volume += 0.25
            if currentR < 255:
                currentR += 15
            if currentG > 0:
                currentG -= 15
            if currentB > 0:
                currentB -= 15
        if button_G.value:
            if volume < 8:
                volume += 0.25
            if currentG < 255:
                currentG += 15
            if currentR > 0:
                currentR -= 15
            if currentB > 0:
                currentB -= 15
        if button_B.value:
            if volume < 8:
                volume += 0.25
            if currentB < 255:
                currentB += 15
            if currentG > 0:
                currentG -= 15
            if currentR > 0:
                currentR -= 15

        cup_display()
        time.sleep(0.01)










