### Upcoming events Egg
### Author: Frans Faase, Renze Nicolai
### License: GPLv3

import ugfx, badge, gc, wifi, utime, appglue
import urequests as requests

schedule = {}

# DRAW
def draw_msg(title, desc):
    ugfx.clear(ugfx.WHITE)
    ugfx.string(0, 0, title, "PermanentMarker22", ugfx.BLACK)
    ugfx.string(0, 25, desc, "Roboto_Regular12", ugfx.BLACK)
    ugfx.set_lut(ugfx.LUT_FASTER)
    ugfx.flush()

# BACK TO HOME
def start_home(pushed):
    if(pushed):
        appglue.home()

def nothing(pressed):
    ugfx.flush()
    pass
    
# SCREEN: EVENT

def screen_event_back(pressed):
    if (pressed):
        screen_eventselect()

def screen_event_flip_left(pressed):
    if (pressed):
        screen_event()
    
def screen_event_flip_right(pressed):
    if (pressed):
        screen_event_detail()

def split_and_draw(x,y,text,max_lines,skip_lines):    
    words = text.split()
    line = ""
    lc = 0
    tl = 0
    for i in range(0,len(words)):
        if len(words[i])>=50:
            print("What the?!?! This word is "+str(len(words[i]))+" characters long: "+words[i])
            tl += 2
            if skip_lines>0:
                skip_lines -= 1
            elif lc<max_lines:
                ugfx.string(x, y, line, "Roboto_Regular12", ugfx.BLACK)
                y += 13
                lc += 1
            if skip_lines>0:
                skip_lines -= 1
            elif lc<max_lines:
                ugfx.string(x, y, words[i], "Roboto_Regular12", ugfx.BLACK)
                y += 13
                lc += 1
            line = ""
        elif len(line+' '+words[i])<50:
            line += ' '+words[i]
        else:
            tl += 1
            if skip_lines>0:
                skip_lines -= 1
            elif lc<max_lines:
                ugfx.string(x, y, line, "Roboto_Regular12", ugfx.BLACK)
                y += 13
                lc += 1
            line = words[i]
    tl += 1
    if skip_lines>0:
        skip_lines -= 1
    elif lc<max_lines:
        ugfx.string(x, y, line, "Roboto_Regular12", ugfx.BLACK)
    return tl

def screen_event_scroll():
    ugfx.area(0,34,ugfx.width(),ugfx.height()-15-34,ugfx.WHITE)
    global scrollPos
    global schedule_event
    split_and_draw(0,35,schedule_event['abstract'],6,scrollPos)
    ugfx.flush()

def screen_event_scroll_up(pressed):
    if pressed:
        global scrollPos
        if scrollPos>0:
            scrollPos -= 1
            screen_event_scroll()
    
def screen_event_scroll_down(pressed):
    if pressed:
        global scrollPos
        global scrollMax
        if scrollPos<scrollMax-6:
            scrollPos += 1
            screen_event_scroll()

def screen_event():
    print("> Screen event")
    global schedule_event
    ugfx.clear(ugfx.WHITE)
    ugfx.string(0, 0, schedule_event['title'], "Roboto_Regular18", ugfx.BLACK)
    ugfx.string(0, 20, schedule_event['subtitle'], "Roboto_Regular12", ugfx.BLACK)
    ugfx.line(0,33,295,33, ugfx.BLACK)
        
    global scrollPos
    scrollPos = 0
    global scrollMax
    scrollMax = split_and_draw(0,35,schedule_event['abstract'],6,0)
        
    ugfx.line(0,ugfx.height()-14,295,ugfx.height()-14, ugfx.BLACK)
    ugfx.string(0, ugfx.height()-12, "B: Back | START: Home | >: Details", "Roboto_Regular12", ugfx.BLACK)
    
    ugfx.input_attach(ugfx.JOY_UP, screen_event_scroll_up)
    ugfx.input_attach(ugfx.JOY_DOWN, screen_event_scroll_down)
    ugfx.input_attach(ugfx.JOY_LEFT, screen_event_flip_left)
    ugfx.input_attach(ugfx.JOY_RIGHT, screen_event_flip_right)
    ugfx.input_attach(ugfx.BTN_SELECT, nothing)
    ugfx.input_attach(ugfx.BTN_A, nothing)
    ugfx.input_attach(ugfx.BTN_B, screen_event_back )
    ugfx.flush()
    
def screen_event_detail():
    print("> Screen event detail")
    global schedule_event
    ugfx.clear(ugfx.WHITE)
    ugfx.string(0, 0, schedule_event['title'], "Roboto_Regular18", ugfx.BLACK)
    ugfx.string(0, 20, schedule_event['subtitle'], "Roboto_Regular12", ugfx.BLACK)
    ugfx.line(0,33,295,33, ugfx.BLACK)    
    ugfx.string(0, 35, "Type: "+schedule_event['type'], "Roboto_Regular12", ugfx.BLACK)
    if (schedule_event['do_not_record']):
        ugfx.string(0, 35+13, "Recording is not allowed!", "Roboto_Regular12", ugfx.BLACK)
    else:
        ugfx.string(0, 35+13, "Recording is allowed ("+schedule_event['recording_license']+").", "Roboto_Regular12", ugfx.BLACK)
        
    ugfx.string(0, 35+13*2, "Language: "+schedule_event['language'], "Roboto_Regular12", ugfx.BLACK)
    ugfx.string(0, 35+13*3, "Room: "+schedule_event['room'], "Roboto_Regular12", ugfx.BLACK)

    #Timezone correction
    localtimestamp = schedule_event['timestamp'] + (2*60*60)
    
    [year, month, day, hour, minute, second, weekday, yearday] = utime.localtime(localtimestamp)
        
    when = "%d-%d-%d %d:%d"% (day, month, year, hour, minute)
        
    ugfx.string(0, 35+13*4, "When: "+when, "Roboto_Regular12", ugfx.BLACK)
    ugfx.string(0, 35+13*5, "Duration: "+schedule_event['duration'], "Roboto_Regular12", ugfx.BLACK)
    
    ugfx.line(0,ugfx.height()-14,295,ugfx.height()-14, ugfx.BLACK)
    ugfx.string(0, ugfx.height()-12, "B: Back | START: Home | <: Abstract", "Roboto_Regular12", ugfx.BLACK)
    
    ugfx.input_attach(ugfx.JOY_UP, nothing)
    ugfx.input_attach(ugfx.JOY_DOWN, nothing)
    ugfx.input_attach(ugfx.JOY_LEFT, screen_event_flip_left)
    ugfx.input_attach(ugfx.JOY_RIGHT, screen_event_flip_right)
    ugfx.input_attach(ugfx.BTN_SELECT, nothing)
    ugfx.input_attach(ugfx.BTN_A, nothing)
    ugfx.input_attach(ugfx.BTN_B, screen_event_back )
    ugfx.flush()

def load_event(guid):
    draw_msg("Loading...", "Downloading JSON...")
    gc.collect()
    try:
        data = requests.get("https://badge.sha2017.org/schedule/event/"+guid+".json")
    except:
        draw_msg("Error", "Could not download JSON!")
        utime.sleep(5)
        screen_eventselect()
        return
    try:
        global schedule_event
        schedule_event = data.json()
    except:
        data.close()
        draw_msg("Error", "Could not decode JSON!")
        utime.sleep(5)
        screen_eventselect()
        return
    
    data.close()
    
    draw_msg("Loading...", "Rendering list...")
    screen_event()
    


def program_main():  
    ugfx.init()
    ugfx.input_init()
    draw_msg("Welcome!","Starting app...")

    ugfx.input_attach(ugfx.BTN_START, start_home)

    draw_msg("Loading...", "WiFi: starting radio...")
    wifi.init()
        
    ssid = badge.nvs_get_str('badge', 'wifi.ssid', 'SHA2017-insecure')
    draw_msg("Loading...", "WiFi: connecting to '"+ssid+"'...")
    timeout = 100
    while not wifi.sta_if.isconnected():
        utime.sleep(0.1)
        timeout = timeout - 1
        if (timeout<1):
            draw_msg("Error", "Timeout while connecting!")
            utime.sleep(5)
            start_home(True)
            break
        else:
            pass
    draw_msg("Loading...", "Downloading JSON...")
    gc.collect()
    try:
        data = requests.get("https://badge.sha2017.org/schedule/upcoming.json")
    except:
        draw_msg("Error", "Could not download JSON!")
        utime.sleep(5)
        start_home(True)
    
    if data.status_code == 404:
        draw_msg("Error", "Data not available on server")
        utime.sleep(5)
        start_home(True)
    
    unsorted_schedule = []
    try:
        unsorted_schedule = data.json()
    except:
        data.close()
        draw_msg("Error", "Could not decode JSON!")
        utime.sleep(5)
        start_home(True)
    
    # sort schedule hy start time ignoring events that start before now	
    global schedule
    schedule = []
    [year, month, day, hour, minute, second, weekday, yearday] = utime.localtime(utime.time())
    from_start = '{:02d}:{:02d}'.format(hour, minute)
    while True:
    	next_start = ""
    	for event in range(0, len(unsorted_schedule)):
        	evstart = unsorted_schedule[event]['start']
        	if evstart > from_start and (next_start == "" or evstart < next_start):
        		next_start = evstart
        if next_start == "":
        	break;
    	for event in range(0, len(unsorted_schedule)):
        	evstart = unsorted_schedule[event]['start']
        	if evstart == next_start:
        		schedule.append(unsorted_schedule[event])
        from_start = next_start
    	
    data.close()
    screen_eventselect()

def screen_eventselect():
    print("> Screen eventselect")
    global schedule
    global options
    ugfx.clear(ugfx.WHITE)
    title = "Select an event"
    ugfx.string(0, 0, title, "Roboto_Regular12", ugfx.BLACK)
    options = ugfx.List(0,15,ugfx.width(),ugfx.height())
    for event in range(0, len(schedule)):
        #print("Adding event "+str(event))
        evstart = schedule[event]['start']
        evtitle = schedule[event]['title']
        evroom = schedule[event]['room']
        title = evstart + " " + evroom + ": " + evtitle
        if (len(title)>55):
            title = title[0:52]+"..."
        options.add_item("%s" % title)
    ugfx.input_attach(ugfx.JOY_UP, nothing)
    ugfx.input_attach(ugfx.JOY_DOWN, nothing)
    ugfx.input_attach(ugfx.JOY_LEFT, nothing)
    ugfx.input_attach(ugfx.JOY_RIGHT, nothing)
    ugfx.input_attach(ugfx.BTN_SELECT, nothing)
    ugfx.input_attach(ugfx.BTN_A, screen_eventselect_submit)
    ugfx.input_attach(ugfx.BTN_B, nothing )
    ugfx.flush()
    
def screen_eventselect_submit(pressed):
    if (pressed):
        global options
        option_id = options.selected_index()
        options.destroy()
        global schedule
        event = schedule[option_id]
        print("> load event: "+event['title']+" ("+event['guid']+")")
        load_event(event['guid'])
    
# Start main application
program_main()