"""
Some parts of this file are from: https://badge.team/projects/card10_nickname
Feel free to take anything from this file and use it for yourself
"""

import buttons
import display
import leds
import light_sensor
import urandom
import utime


# Pure constants
BOTTOM_LED_COUNT = 4
BOTTOM_LED_FIRST = 11
BOTTOM_LEDS_BOTTOM_LEFT = 11
BOTTOM_LEDS_BOTTOM_RIGHT = 12
BOTTOM_LEDS_TOP_LEFT = 13
BOTTOM_LEDS_TOP_RIGHT = 14
BRIGHTNESS_MAX = 400
BRIGHTNESS_THRESHOLD = 40
DIM_MAX = 8
DIM_MIN = 1
DVD_LOGO_BW = [
    [(2, 19), (3, 228), (4, 239), (5, 239), (6, 239), (7, 239), (8, 239), (9, 239), (10, 239), (11, 239), (12, 239), (13, 239), (14, 239), (15, 239), (16, 239), (17, 240), (18, 197), (25, 42), (26, 233), (27, 239), (28, 239), (29, 239), (30, 239), (31, 239), (32, 239), (33, 239), (34, 239), (35, 236), (36, 214), (37, 169), (38, 54)],
    [(2, 42), (3, 253), (4, 255), (5, 255), (6, 255), (7, 255), (8, 255), (9, 255), (10, 255), (11, 254), (12, 254), (13, 254), (14, 254), (15, 254), (16, 254), (17, 254), (18, 255), (19, 26), (24, 25), (25, 254), (26, 254), (27, 254), (28, 255), (29, 255), (30, 255), (31, 255), (32, 255), (33, 255), (34, 255), (35, 255), (36, 254), (37, 254), (38, 255), (39, 135)],
    [(2, 5), (3, 37), (4, 37), (5, 37), (6, 43), (7, 48), (8, 54), (9, 111), (10, 239), (11, 255), (12, 254), (13, 254), (14, 254), (15, 254), (16, 254), (17, 254), (18, 255), (19, 121), (24, 219), (25, 254), (26, 254), (27, 252), (28, 69), (29, 37), (30, 37), (31, 36), (32, 48), (33, 49), (34, 87), (35, 207), (36, 255), (37, 254), (38, 254), (39, 255), (40, 92)],
    [(2, 107), (3, 226), (4, 224), (5, 225), (6, 86), (11, 198), (12, 255), (13, 254), (14, 254), (15, 254), (16, 252), (17, 254), (18, 254), (19, 194), (22, 1), (23, 191), (24, 255), (25, 254), (26, 255), (27, 120), (28, 190), (29, 224), (30, 224), (31, 233), (36, 136), (37, 255), (38, 254), (39, 254), (40, 252)],
    [(2, 190), (3, 255), (4, 254), (5, 252), (6, 58), (11, 103), (12, 255), (13, 254), (14, 254), (15, 253), (16, 205), (17, 254), (18, 254), (19, 249), (20, 2), (22, 133), (23, 255), (24, 254), (25, 254), (26, 138), (27, 11), (28, 234), (29, 254), (30, 254), (31, 218), (36, 11), (37, 255), (38, 254), (39, 254), (40, 255), (41, 30)],
    [(2, 255), (3, 254), (4, 254), (5, 249), (6, 32), (11, 158), (12, 255), (13, 254), (14, 255), (15, 224), (16, 95), (17, 255), (18, 254), (19, 255), (20, 99), (21, 110), (22, 255), (23, 254), (24, 255), (25, 184), (26, 1), (27, 25), (28, 251), (29, 254), (30, 254), (31, 165), (36, 29), (37, 255), (38, 254), (39, 254), (40, 255), (41, 9)],
    [(1, 41), (2, 255), (3, 254), (4, 254), (5, 247), (6, 4), (10, 73), (11, 253), (12, 254), (13, 254), (14, 255), (15, 71), (17, 255), (18, 254), (19, 255), (20, 231), (21, 248), (22, 254), (23, 255), (24, 211), (27, 65), (28, 255), (29, 254), (30, 254), (31, 114), (35, 11), (36, 174), (37, 254), (38, 254), (39, 255), (40, 171)],
    [(1, 109), (2, 255), (3, 254), (4, 255), (5, 199), (7, 13), (8, 93), (9, 216), (10, 253), (11, 254), (12, 254), (13, 255), (14, 168), (17, 132), (18, 255), (19, 254), (20, 254), (21, 254), (22, 254), (23, 251), (24, 15), (27, 139), (28, 255), (29, 254), (30, 255), (31, 62), (33, 30), (34, 128), (35, 239), (36, 254), (37, 254), (38, 254), (39, 231), (40, 12)],
    [(1, 174), (2, 255), (3, 254), (4, 254), (5, 254), (6, 255), (7, 255), (8, 255), (9, 255), (10, 254), (11, 255), (12, 255), (13, 138), (17, 31), (18, 248), (19, 254), (20, 254), (21, 254), (22, 250), (23, 41), (27, 213), (28, 255), (29, 254), (30, 254), (31, 255), (32, 255), (33, 255), (34, 255), (35, 254), (36, 255), (37, 255), (38, 188), (39, 28)],
    [(0, 4), (1, 209), (2, 255), (3, 255), (4, 255), (5, 255), (6, 254), (7, 254), (8, 251), (9, 246), (10, 239), (11, 167), (12, 17), (17, 2), (18, 220), (19, 254), (20, 254), (21, 255), (22, 81), (27, 255), (28, 255), (29, 255), (30, 255), (31, 255), (32, 254), (33, 252), (34, 248), (35, 242), (36, 204), (37, 61)],
    [(0, 1), (1, 49), (2, 55), (3, 55), (4, 55), (5, 55), (6, 55), (7, 52), (8, 44), (9, 29), (10, 7), (18, 97), (19, 255), (20, 255), (21, 110), (26, 6), (27, 58), (28, 55), (29, 55), (30, 55), (31, 55), (32, 54), (33, 48), (34, 35), (35, 16)],
    [(19, 241), (20, 154)],
    [(8, 34), (9, 70), (10, 101), (11, 127), (12, 152), (13, 170), (14, 186), (15, 200), (16, 211), (17, 216), (18, 220), (19, 240), (20, 224), (21, 217), (22, 209), (23, 197), (24, 183), (25, 167), (26, 147), (27, 124), (28, 95), (29, 64), (30, 27)],
    [(1, 17), (2, 93), (3, 150), (4, 187), (5, 217), (6, 243), (7, 255), (8, 255), (9, 255), (10, 209), (11, 253), (12, 238), (13, 247), (14, 237), (15, 234), (16, 255), (17, 191), (18, 182), (19, 250), (20, 255), (21, 224), (22, 180), (23, 225), (24, 255), (25, 255), (26, 172), (27, 209), (28, 255), (29, 255), (30, 255), (31, 255), (32, 239), (33, 212), (34, 182), (35, 142), (36, 81), (37, 2)],
    [(0, 128), (1, 255), (2, 255), (3, 254), (4, 254), (5, 254), (6, 254), (7, 254), (8, 254), (9, 255), (10, 169), (11, 187), (12, 98), (13, 236), (14, 170), (15, 165), (16, 255), (17, 32), (18, 197), (19, 74), (20, 254), (21, 115), (22, 147), (23, 227), (24, 255), (25, 30), (26, 205), (27, 125), (28, 195), (29, 255), (30, 254), (31, 254), (32, 254), (33, 254), (34, 254), (35, 255), (36, 255), (37, 255), (38, 78)],
    [(0, 101), (1, 255), (2, 255), (3, 255), (4, 254), (5, 254), (6, 254), (7, 254), (8, 254), (9, 254), (10, 251), (11, 93), (12, 94), (13, 255), (14, 171), (15, 166), (16, 255), (17, 39), (18, 244), (19, 74), (20, 254), (21, 114), (22, 178), (23, 242), (24, 250), (25, 17), (26, 255), (27, 168), (28, 180), (29, 255), (30, 254), (31, 254), (32, 254), (33, 254), (34, 254), (35, 255), (36, 255), (37, 245), (38, 59)],
    [(2, 69), (3, 132), (4, 175), (5, 201), (6, 225), (7, 245), (8, 255), (9, 255), (10, 255), (11, 189), (12, 245), (13, 255), (14, 227), (15, 225), (16, 255), (17, 159), (18, 146), (19, 233), (20, 255), (21, 209), (22, 144), (23, 213), (24, 255), (25, 246), (26, 133), (27, 173), (28, 255), (29, 255), (30, 255), (31, 242), (32, 221), (33, 197), (34, 169), (35, 121), (36, 54)],
    [(9, 28), (10, 60), (11, 87), (12, 112), (13, 132), (14, 146), (15, 161), (16, 171), (17, 177), (18, 181), (19, 184), (20, 179), (21, 177), (22, 169), (23, 157), (24, 144), (25, 128), (26, 108), (27, 83), (28, 55), (29, 23)],
]
ROCKET_LED_MAX_BRIGHTNESS = 31
ROCKET_LED_NUM = 3
SLEEP = 0.5
TOP_LED_FIRST = 1
TOP_LED_COUNT = 8
X_MAX = 160
X_STEP = 1
Y_MAX = 80
Y_STEP = 2

# Calculated constants (calculated from pure constants)
X_SIZE = max([max([i for i, _ in r]) for r in DVD_LOGO_BW])
Y_SIZE = len(DVD_LOGO_BW)


def get_random_color():
    return [
        urandom.randint(0, 255),
        urandom.randint(0, 255),
        urandom.randint(0, 255),
    ]

def button_handling(last_btn_poll):
    pressed = buttons.read(
        buttons.TOP_LEFT |
        buttons.TOP_RIGHT |
        buttons.BOTTOM_LEFT |
        buttons.BOTTOM_RIGHT
    )
    buttons_pressed = {
        'tl': False,
        'tr': False,
        'bl': False,
        'br': False,
    }
    if utime.time() - last_btn_poll >= 1:
        last_btn_poll = utime.time()
        if pressed & buttons.TOP_LEFT != 0:
            buttons_pressed['tl'] = True
        if pressed & buttons.TOP_RIGHT != 0:
            buttons_pressed['tr'] = True
        if pressed & buttons.BOTTOM_LEFT != 0:
            buttons_pressed['bl'] = True
        if pressed & buttons.BOTTOM_RIGHT != 0:
            buttons_pressed['br'] = True
    return buttons_pressed, last_btn_poll

def move(x, y, dir_x, dir_y):
    x += dir_x
    y += dir_y
    borders = []
    if dir_x > 0 and x+X_SIZE >= X_MAX:
        borders.append('r')
        x = X_MAX-X_SIZE
        dir_x = -X_STEP
    elif dir_x < 0 and x <= 0:
        borders.append('l')
        x = 0
        dir_x = X_STEP
    if dir_y > 0 and y+Y_SIZE >= Y_MAX:
        borders.append('b')
        y = Y_MAX-Y_SIZE
        dir_y = -Y_STEP
    elif dir_y < 0 and y <= 0:
        borders.append('t')
        y = 0
        dir_y = Y_STEP
    return x, y, dir_x, dir_y, borders

def render_disp(x, y, fg_color, brightness):
    if brightness < BRIGHTNESS_THRESHOLD:
        bg_color = [0, 0, 0]
    else:
        bg_color = [255, 255, 255]
    with display.open() as disp:
        disp.clear()
        disp.rect(0, 0, X_MAX, Y_MAX, col=bg_color, filled=True)
        for i, row in enumerate(DVD_LOGO_BW):
            for j, bw in row:
                if brightness >= BRIGHTNESS_THRESHOLD:
                    bw = 255 - bw
                col = [int((c/255.0)*bw) for c in fg_color]
                disp.pixel(x+j, y+i, col=col)
        disp.update()

def render_leds(
    x,
    borders,
    fg_color,
    brightness,
):
    dim = int(float(brightness) / BRIGHTNESS_MAX * (DIM_MAX - DIM_MIN)) + DIM_MIN
    leds.dim_top(dim)
    leds.dim_bottom(dim)
    start_led = int(float(x) / X_MAX * TOP_LED_COUNT)
    end_led = int(start_led + X_SIZE / (float(X_MAX) / TOP_LED_COUNT) + 1)
    def translate_led(index):
        return ((TOP_LED_COUNT + 1) - TOP_LED_FIRST) - index
    start_led = translate_led(start_led)
    end_led = translate_led(end_led)
    for i in range(TOP_LED_FIRST, TOP_LED_FIRST + TOP_LED_COUNT):
        leds.prep(i, [0, 0, 0])
        if start_led >= i > end_led:
            leds.prep(i, fg_color)
    def update_bottom_leds(index):
        for i in range(BOTTOM_LED_FIRST, BOTTOM_LED_FIRST + BOTTOM_LED_COUNT):
            if i == index:
                leds.prep(i, fg_color)
            else:
                leds.prep(i, [0, 0, 0])
    if 'b' in borders and 'l' in borders:
        update_bottom_leds(BOTTOM_LEDS_BOTTOM_LEFT)
    if 'b' in borders and 'r' in borders:
        update_bottom_leds(BOTTOM_LEDS_BOTTOM_RIGHT)
    if 't' in borders and 'r' in borders:
        update_bottom_leds(BOTTOM_LEDS_TOP_RIGHT)
    if 't' in borders and 'l' in borders:
        update_bottom_leds(BOTTOM_LEDS_TOP_LEFT)
    leds.update()
    for i in range(ROCKET_LED_NUM):
        leds.set_rocket(i, 0)
    if 'l' in borders:
        leds.set_rocket(0, ROCKET_LED_MAX_BRIGHTNESS)
    if 't' in borders:
        leds.set_rocket(1, ROCKET_LED_MAX_BRIGHTNESS)
    if 'r' in borders:
        leds.set_rocket(2, ROCKET_LED_MAX_BRIGHTNESS)

def main():
    x = int(urandom.randint(0, X_MAX-X_SIZE) / 4) * 4
    y = int(urandom.randint(0, Y_MAX-Y_SIZE) / 4) * 4
    dir_x = X_STEP
    dir_y = Y_STEP
    running = True
    last_btn_poll = utime.time()
    fg_color = get_random_color()
    while True:
        buttons_pressed, last_btn_poll = button_handling(last_btn_poll)
        if buttons_pressed['bl']:
            running = not running
        while running:
            buttons_pressed, last_btn_poll = button_handling(last_btn_poll)
            if buttons_pressed['bl']:
                running = not running
            x, y, dir_x, dir_y, borders = move(
                x,
                y,
                dir_x,
                dir_y,
            )
            if len(borders) > 0:
                fg_color = get_random_color()
            brightness = light_sensor.get_reading()
            render_disp(x, y, fg_color, brightness)
            render_leds(
                x,
                borders,
                fg_color,
                brightness,
            )
        utime.sleep(SLEEP)

main()