import machine, math, ugfx, gc, easywifi, badge #, deepsleep
import urequests as requests


TS_WIDTH = 25
TS_HEIGHT = 10

REFRESH_RATE = 5 * 60 * 1000 # 5 minutes
LAT = 51.9773
LON =  5.94035
url = "https://youp.net/volweer.php?lat=%f&lon=%f" % (LAT, LON)

def getDisplayName(time):
    if time < 6:
        return "Nacht"
    elif time < 12:
        return "Ochtend"
    elif time < 18:
        return "Middag"
    elif time <= 24:
        return "Avond"

def draw_graph(x, y, width, height, samples, scale=1.0, colour=ugfx.BLACK):
    """Draws a graph at the specified coordinates.

    Draws a graph across the full length of the specified area, capping values
    at (height / scale)
    """

    # How many samples can we fit?
    sample_width = width / (len(samples) - 1)
    sample_width_round = int(sample_width + .5)
    
    prev_val = 0
    for i, item in enumerate(samples):
        val = max(0, height - 1 - int(item * scale + .5))
        if i > 0:
            left_edge = int(x + (i - 1) * sample_width + .5)
            if left_edge + sample_width_round >= width:
                sample_width_round = int(width - left_edge - 1)

            # The right edge won't be drawn.
            ugfx.fill_polygon(int(x + (i - 1) * sample_width + .5), y, [
                                  (0, height - 1), (0, prev_val),
                                  (sample_width_round, val), (sample_width_round, height - 1)
                                  ], colour)

        prev_val = val

def _raw_to_mm(raw):
    raw = int(raw)
    if raw == 0: return 0.0
    return 10 ** ((raw - 109) / 32)

def get_downpour():
    r = requests.get(url)
    gc.collect()
    data = r.json()
    r.close()
    return data

def draw_rain_graph(x, y, width, height, scale=1.0, colour=ugfx.BLACK):
    global downpour
    """Draws a rain graph at the specified coordinates.

    Uses 14 pixels for the time, and then draws a graph across the full length
    of the specified area, capping values at (height / scale) - 14 millimeters
    """

    buien=downpour['bui']
    # How many timestmaps can we fit?
    num_items = len(buien)
    period = math.ceil(num_items * 1.5 * TS_WIDTH / (width - TS_WIDTH))

    sample_width = int(width / (num_items - 1))
    
    text_y = y + height - TS_HEIGHT
    bui=[]
    maxval=0
    for d in range(num_items):
        if d % period == 0:
            text_x = x + d * sample_width - ugfx.get_string_width(buien[d]['time'], 'Roboto_Regular12') // 2
            
            # Corner case: screen edge
            if text_x < 0:
                text_x = 0
            elif text_x + TS_WIDTH > x + width:
                text_x = x + width - TS_WIDTH

            ugfx.string(text_x, text_y, buien[d]['time'], "Roboto_Regular10", colour)
        bui.append(buien[d]['rain'])
        maxval=max(maxval,buien[d]['rain'])

    ugfx.string(x + width - TS_WIDTH, text_y, buien[d]['time'], "Roboto_Regular10", 0x888888)
    maxval=min(300,maxval)
    maxval=(maxval/300)
    maxval=round(5*maxval)
    maxval=str(maxval)
    maxval=int('0x'+maxval+maxval+maxval+maxval+maxval+maxval,16)
    maxval=0xAAAAAA+maxval
    draw_graph(x, y, width, height - (TS_HEIGHT - 2), bui, scale, maxval)

def refresh():
    global downpour
    retry = 0
    while len(downpour) == 0 and retry < 10:
        downpour = get_downpour()
        retry += 1

    try:
        if len(downpour) == 0:
            raise RuntimeError('Buienradar gaf geen informatie')
    except Exception as e: #CatchAll exceptions
        print('Error on 129: ', e)
        ugfx.string_box(0, 0, 296, 128,
                        str(e), "Roboto_Regular12",
                        ugfx.BLACK, ugfx.justifyCenter)
        return

def setup():
    global downpour
    downpour = []
    #refresh()
    pass

def loop():
    global downpour
    easywifi.enable()
    refresh()


    ugfx.init()
    ugfx.clear(ugfx.WHITE);
    ugfx.string(10,10,"Het weer","PermanentMarker22", 0)
    ugfx.string(110,100,"wordt geladen...","Roboto_Regular12", 0)
    ugfx.flush()
    ugfx.clear(ugfx.WHITE);

    icons = {
    "clear-day": "\uf00d",
    "clear-night": "\uf02e",
    "rain": "\uf019",
    "snow": "\uf01b",
    "sleet": "\uf0b5",
    "wind": "\uf050",
    "fog": "\uf021",
    "cloudy": "\uf041",
    "partly-cloudy-day": "\uf002",
    "partly-cloudy-night": "\uf086"
    }

    try:
            import consts
            consts.INFO_FIRMWARE_NAME
            #Workaround for bug in platform firmware...
            icons = {
            "clear-day": chr(1),
            "clear-night": chr(),
            "rain": chr(8),
            "snow": chr(15),
            "sleet": chr(15),
            "wind": chr(18),
            "fog": chr(17),
            "cloudy": chr(4),
            "partly-cloudy-day": chr(2),
            "partly-cloudy-night": chr(3)
            }
    except:
      pass

   # loading screen
    buien=downpour['bui']
    MSG_TOP = 0
    SCREEN_WIDTH=296
    if len(buien) == 0:
        ugfx.string_box(0, MSG_TOP, 296, MSG_TOP,
                        'Ophalen van regenverwachting is mislukt', 'Roboto_Regular10',
                        ugfx.BLACK, ugfx.justifyLeft)
        return REFRESH_RATE, 0


    start = end = 0
    for d in range(len(buien)):
        if int(buien[d]['rain']) > 0 and start == 0:
            start = buien[d]['time']
        elif int(buien[d]['rain']) == 0 and start != 0 and end == 1:
            end = buien[d]['time']

    if start != 0:
        timepos = [10, 47]
        iconpos = [10, 61]
        temppos = [10, 112]
        if end != 0:
            frm=(int(start[0:2])*60*60)+(int(start[3:5])*60)
            to=(int(end[0:2])*60*60)+(int(end[3:5])*60)
            if to < frm:
                to = to + (24*60*60)
            if to-frm > 3600:
                duration = "%d uur en %d minuten"%(round((to-frm)/60/60), ((to-frm)/60)%60)
            else:
                duration = "%d minuten"%(((to-frm)/60))
        else:
            duration = 'een tijd'

        ugfx.string_box(0, 0, 296, 15,
            'Om %s regent het %s' % (start, duration), 'Roboto_Regular12',
            ugfx.BLACK, ugfx.justifyLeft)
        draw_rain_graph(0, 0, 296, timepos[1]-2, (timepos[1]/500), ugfx.BLACK)
    else:
        timepos = [11, 27]
        iconpos = [10, 51]
        temppos = [10, 110]
        #'Roboto_Regular12
        #'GEEN REGEN VERWACHT', 'DejaVuSans12',
        ugfx.string_box(0, 0, 296, timepos[1],
            'Voorlopig nog geen regen', 'PermanentMarker22',
            0x888888, ugfx.justifyCenter)

    hourly = downpour["hourly"]["data"]
    ugfx.line(0, timepos[1], 296, timepos[1], 0)

    timepos.append(15) #fontheight 
    iconpos.append(48) #fontheight 
    temppos.append(20) #fontheight 
    timepos.append(timepos[1]+timepos[2]) #lineheight 
    iconpos.append(iconpos[1]+iconpos[2]) #lineheight 
    temppos.append(temppos[1]+temppos[2]) #lineheight 
    timepos.append('pixelade13') #font
    iconpos.append('weather42') #font
    temppos.append('DejaVuSans20') #font
    posx=[0,int(SCREEN_WIDTH*0.24),int(SCREEN_WIDTH*0.48),int(SCREEN_WIDTH*0.72),int(SCREEN_WIDTH*0.96)]

    dp = hourly[0]
    time = int(str(dp["timestamp"])[8:10])
    ugfx.string_box(posx[0], timepos[1], posx[1]-posx[0], timepos[2], getDisplayName(time), timepos[4], 0, ugfx.justifyCenter)
    ugfx.string(posx[0]+12, iconpos[1],icons[dp["icon"]], iconpos[4], 0)
    ugfx.string_box(posx[0], temppos[1], posx[1]-posx[0], temppos[2], str(int(dp["temperature"]))+"°C", temppos[4], 0, ugfx.justifyCenter)

    dp = hourly[6]
    time = int(str(dp["timestamp"])[8:10])
    ugfx.string_box(posx[1], timepos[1], posx[2]-posx[1], timepos[2], getDisplayName(time), timepos[4], 0, ugfx.justifyCenter)
    ugfx.string(posx[1]+12, iconpos[1],icons[dp["icon"]], iconpos[4], 0)
    ugfx.string_box(posx[1], temppos[1], posx[2]-posx[1], temppos[2], str(int(dp["temperature"]))+"°C", temppos[4], 0, ugfx.justifyCenter)

    dp = hourly[12]
    time = int(str(dp["timestamp"])[8:10])
    ugfx.string_box(posx[2], timepos[1], posx[3]-posx[2], timepos[2], getDisplayName(time), timepos[4], 0, ugfx.justifyCenter)
    ugfx.string(posx[2]+12, iconpos[1],icons[dp["icon"]], iconpos[4], 0)
    ugfx.string_box(posx[2], temppos[1], posx[3]-posx[2], temppos[2], str(int(dp["temperature"]))+"°C", temppos[4], 0, ugfx.justifyCenter)

    dp = hourly[18]
    time = int(str(dp["timestamp"])[8:10])
    ugfx.string_box(posx[3], timepos[1], posx[4]-posx[3], timepos[2], getDisplayName(time), timepos[4], 0, ugfx.justifyCenter)
    ugfx.string(posx[3]+12, iconpos[1],icons[dp["icon"]], iconpos[4], 0)
    ugfx.string_box(posx[3], temppos[1], posx[4]-posx[3], temppos[2], str(int(dp["temperature"]))+"°C", temppos[4], 0, ugfx.justifyCenter)

    status(timepos)


    #ugfx.flush(ugfx.LUT_FULL);
    ugfx.flush(ugfx.GREYSCALE);
    badge.eink_busy_wait()
    print('Entering deep sleep...')
    machine.deepsleep(2*60*60*1000) #for two hours # didn't work, sleeps forever
    #deepsleep.start_sleeping(2*60*60*1000) #for two hours #Same story
    print("Not entered deep sleep somehow...")
    return REFRESH_RATE

def status(timepos):
    global downpour
    vbatt = badge.battery_volt_sense()/1000.0
    vmax=4.1
    vmin=3.5
    if vbatt >= vmax:
        battpix=1.0
    elif vbatt <= vmin:
        battpix=0.0
    else:
        battpix=(1-1*(vmax-vbatt)/(vmax-vmin))

    ugfx.string_box(250, timepos[1],46,timepos[2],downpour["timestamp"], "pixelade13", 0, ugfx.justifyRight)
    ugfx.string_box(250, timepos[1]+9,46,timepos[2], downpour["datestamp"], "pixelade13", 0, ugfx.justifyRight)
    ugfx.string_box(0, timepos[1]+9,246,timepos[2], downpour["city"], "pixelade13", 0, ugfx.justifyLeft)
    
    ugfx.line(294,0,288,0, 0)
    ugfx.line(288,0,288,6, 0)
    ugfx.line(288,6,294,6, 0)
    ugfx.line(294,6,294,5, 0)
    ugfx.line(294,0,294,1, 0)
    ugfx.line(295,4,295,2, 0)
    ugfx.thickline(289,3,(289+round(6*battpix)),3,0,6,False)

def draw(y):
    return REFRESH_RATE, 128