"""
Displays Blinkenlights Movies https://wiki.blinkenarea.org/index.php/Blinkenlights_Movie

card10 firmware version >= 1.6 recommended

Find more movies at https://stefan.blinkenarea.org/movies/18x8-1/

Authors: took, b2ag
All rites reversed
Not for military use
"""

import color, leds, buttons, display, os, utime, light_sensor, vibra
from urandom import choice, seed

size_x = 18
size_y = 8
# frame[size_y][size_x] = 0
frame = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
movie_files = []


def myprint(msg):
    print('blinken10ng: ' + str(msg))


def mywait(msec=500):
    utime.sleep_ms(msec)


def clear_frame(size_x=18, size_y=8):
    global frame
    for x in range(size_x):
        for y in range(size_y):
            frame[y][x] = 0


def render_text(msg, delay=900):
    msg = str(msg)
    delay = int(delay)
    with display.open() as disp:
        disp.clear()
        offset_y = 2
        for line in msg.split('\n'):
            offset_y = offset_y + 11
            disp.print(line, posx=80 - round(len(line) / 2 * 14), posy=offset_y)
        disp.update()
        disp.close()
    mywait(delay)


def draw_blinken_screen(pixel_color=color.RED, size_x=18, size_y=8, left_margin=8, top_margin=5, pixel_width=5,
                        pixel_height=7, pad_x=3,
                        pad_y=2, line_width=1):
    with display.open() as disp:
        disp.clear()
        for x in range(size_x):
            for y in range(size_y):
                if frame[y][x] > 0:
                    disp.rect(left_margin + (x * (pixel_width + pad_x)), top_margin + (y * (pixel_height + pad_y)),
                              left_margin + (x * (pixel_width + pad_x)) + pixel_width,
                              top_margin + (y * (pixel_height + pad_y)) + pixel_height, col=pixel_color, filled=True,
                              size=line_width)
        disp.update()
        disp.close()


def play_blinken_blm_file(filename, size_x=18, size_y=8):
    global frame
    f = open(filename, 'r')
    frame_duration = 0
    frame_y = 0
    pc = choice(
        [color.RED, color.RED, color.BLUE, color.WHITE, color.CHAOSBLUE_DARK, color.CHAOSBLUE, color.CAMPGREEN_DARK,
         color.CAMPGREEN])
    for row in f:
        if row[0] == "#":
            continue
        if row[0] == "@":
            # myprint('duration: ' + row)
            frame_duration = int(row.replace("@", ""))
            clear_frame()
            frame_y = 0
            continue
        if len(row) > size_x:
            for x in range(size_x):
                # myprint('row: ' + row)
                frame[frame_y][x] = int(row[x])
            frame_y = frame_y + 1
            if frame_y == size_y:
                # myprint('render screen')
                draw_blinken_screen(pixel_color=pc, size_x=size_x, size_y=size_y)
                mywait(frame_duration)
                clear_frame()
                frame_y = 0
    f.close()


def search_all_movie_files():
    global movie_files
    myprint('Searching movies')
    paths = ['.', './apps/blinken10ng/movies', './apps/blinken10ng', './movies']
    movie_files = []
    for path in paths:
        myprint('Info: Search Path: {}'.format(str(path)))
        try:
            files = os.listdir(path)
        except OSError as e:
            # myprint('os.listdir failed for ' + path)
            myprint('Info: Expected Exception: {}'.format(str(e)))
            continue
        for file in files:
            if (len(file) > 4 and file[-4:] == '.blm'):
                file_short = file[:-4]
                myprint('Found blm: ' + file_short)
                movie_files.append({
                    "file_short": file_short,
                    "path": path,
                    "file": file,
                    "foo": 23
                })
            if (len(file) > 8 and file[-8:] == '.blm.txt'):
                file_short = file[:-8]
                render_text('Found txt\n' + file_short)
                movie_files.append({
                    "file_short": file_short,
                    "path": path,
                    "file": file,
                    "foo": 23
                })
    myprint('Search done')
    # render_text('Search\ndone', delay=250)
    movie_files_length = len(movie_files)
    if movie_files_length is 0:
        render_text('No movie\nfiles found', delay=4000)
        os.exit(1)
    render_text('{}\nmovies found'.format(movie_files_length), delay=2000)


seed(light_sensor.get_reading())
try:
    search_all_movie_files()
except Exception as e:
    myprint('Warning: {}'.format(str(e)))
    render_text('Warning:\n500')
    os.exit(1)

try:
    while True:
        movie_file = choice(movie_files)
        vibra.vibrate(10)
        mywait(700)
        myprint('Info: Play movie {}'.format(str(movie_file['file_short'])))
        render_text('Play File\n{}'.format(movie_file['file_short']))
        play_blinken_blm_file(movie_file['path'] + '/' + movie_file['file'])
        mywait(10)
except Exception as e:
    myprint('Error: {}'.format(str(e)))
    render_text('Error\n500')
    os.exit(1)
