import wifi, badge, ugfx, utime, easydraw, easywifi, gc, machine, woezel
import urequests as requests

import display, buttons, orientation

apiNewestImage = "https://e621.net/posts.json?limit=1&tags="
e621Header = {"User-Agent": "HackerHotelBadge/0.0.1"}
tempFileName = "temp.png"
path = "/lib/e621/" # woezel deletes this folder between updates, but only temporary data is stored here
prevId = 0
failCounter = 0
updateInterval = 5000

menuEntries = ['Rating', 'Filter']
menuOptions = [['All', 'SFW', 'NSFW'], ['All', 'Male only', 'Canine', 'Dragon', 'Vore', 'Anthro', 'Feral']]
menuOptionSel = [0, 0]
menuIdx = 0
apiRatings = ['', 'rating:s', 'rating:e']
apiFilters = ['', '-female -breasts -girly -pussy', 'canine', 'dragon', 'vore', 'anthro', 'feral']

lastButtonPress = 0
buttonTimeout = 300

white = 0xFFFFFF
black = 0x000000
greyFast = display.FLAG_LUT_GREYSCALE | display.FLAG_LUT_FASTEST
greyNormal = display.FLAG_LUT_GREYSCALE | display.FLAG_LUT_NORMAL

def loadSettings():
    for i in range(len(menuEntries)):
        menuOptionSel[i] = badge.nvs_get_u8('e621', 'menuSel_%s' % i, 0)

def saveSettings():
    for i in range(len(menuEntries)):
        badge.nvs_set_u8('e621', 'menuSel_%s' % i, menuOptionSel[i])

def drawMenu(shouldFlush):
    display.drawRect(0, display.height() - 15 - len(menuEntries) * 10, display.width(), len(menuEntries) * 12, True, white)
    for i in range(len(menuEntries)):
        yPos = (display.height() - 15) - (10 * (len(menuEntries) - i))
        if menuIdx == i:
            display.drawText(0, yPos, ">", black)
        display.drawText(8, yPos, menuEntries[i] + ": " + menuOptions[i][menuOptionSel[i]], black)
    if shouldFlush:
        display.flush(greyFast)
    return

def btn_right(pressed):
    if pressed:
        menuOptionSel[menuIdx] += 1
        if menuOptionSel[menuIdx] >= len(menuOptions[menuIdx]):
            menuOptionSel[menuIdx] = 0
        global lastButtonPress
        lastButtonPress = utime.ticks_ms()

def btn_left(pressed):
    if pressed:
        menuOptionSel[menuIdx] -= 1
        if menuOptionSel[menuIdx] < 0:
            menuOptionSel[menuIdx] = len(menuOptions[menuIdx]) - 1
        global lastButtonPress
        lastButtonPress = utime.ticks_ms()

def btn_down(pressed):
    global menuIdx
    if pressed:
        menuIdx += 1
        if menuIdx >= len(menuEntries):
            menuIdx = 0
        global lastButtonPress
        lastButtonPress = utime.ticks_ms()

def btn_up(pressed):
    global menuIdx
    if pressed:
        menuIdx -= 1
        if menuIdx < 0:
            menuIdx = len(menuEntries) - 1
        global lastButtonPress
        lastButtonPress = utime.ticks_ms()

def btn_b(pressed):
    if pressed:
        system.launcher() # Return to launcher

# color: [g, r, b, w]
def setLedColor(color):
    ledData = b""
    for i in range(6):
        ledData += bytes(color)
    badge.leds_send_data(ledData)

def notify():
    setLedColor([0, 0, 0, 255])
    badge.vibrator_activate(5)
    setLedColor([0, 0, 0, 0])

def drawError(text):
    display.drawRect(0, display.height() - 12, display.width(), 12, True, white)
    display.drawText(0, display.height() - 12, text, black)
    display.flush(greyFast)

def viewPreview(post):
    try:
        url = post['preview']['url']
        width = post['preview']['width']
        height = post['preview']['height']
        xOffset = int((display.width() - width) / 2)

        print("Downloading image...")
        # data = requests.get(url, headers=e621Header)
        # have to use an external jpg to png converter because ugfx doesn't display jpgs anymore :(
        data = requests.get("http://prv.lesosoftware.com/aspng.php?img=" + url, headers=e621Header)
        gc.collect()
        img_data = data.content
        data.close()
        gc.collect()

        print("Displaying image...")
        notify()
        display.drawFill(white)
        drawMenu(False)
        display.drawPng(xOffset, 0, img_data)
        display.drawText(0, height, "e621.net/post/show/", black)
        display.drawText(8, height + 10, str(post['id']), black)
        display.drawText(0, height + 24, "Artist: " + ', '.join(post['tags']['artist']), black)
        display.flush(greyNormal)
        gc.collect()
        return True
    except Exception as e: 
        print("Failed")
        print(e)
        # drawError("ERR: img rend - " + type(e).__name__)
        return False

def fetchE621(apiUrl):
    global failCounter
    try:
        data = requests.get(apiUrl, headers=e621Header)
        failCounter = 0
        return data.json()
    except:
        failCounter += 1
        drawError("ERR: API download fail %s" % failCounter)
        return False

def update():
    global prevId
    url = apiNewestImage
    url += apiRatings[menuOptionSel[0]] + ' '
    url += apiFilters[menuOptionSel[1]]
    url = url.replace(' ', '%20')
    posts = fetchE621(url)['posts']
    if posts != False:
        if posts[0]['id'] != prevId:
            print("new post found!")
            drawMenu(False)
            display.drawText(0, display.height() - 12, "Loading new image...", black)
            display.flush(greyFast)
            prevId = posts[0]['id']
            viewPreview(posts[0])


def init():
    orientation.default()
    easydraw.msg("e621 notifier.")
    easydraw.msg("Notifies you about every new upload on e621.net")
    easydraw.msg("Please be patient with the menu, it still registers every key press!")
    easywifi.enable()
    if easywifi.state==False:
        easydraw.msg("You need network for this app!","FAILURE")
        easydraw.msg("Waiting 5 seconds to try again!")
        badge.eink_busy_wait()
        # machine.deepsleep(5000)
        init()
        return
    easydraw.msg("Checking for updates")
    try:
        woezel.install('e621')
        easydraw.msg("Updated! Rebooting now!")
        badge.eink_busy_wait()
        system.start("e621")
        return
    except:
        badge.vibrator_init()
        badge.leds_init()
        badge.leds_enable()
        buttons.attach(buttons.BTN_B, btn_b)
        buttons.attach(buttons.BTN_UP, btn_up)
        buttons.attach(buttons.BTN_DOWN, btn_down)
        buttons.attach(buttons.BTN_LEFT, btn_left)
        buttons.attach(buttons.BTN_RIGHT, btn_right)
        loadSettings()
        display.drawFill(white)
        display.flush()

lastUpdate = 0
def run():
    while True:
        global lastUpdate, lastButtonPress
        now = utime.ticks_ms()
        if now - lastUpdate > updateInterval:
            lastUpdate = utime.ticks_ms()
            update()
        if now - lastButtonPress > buttonTimeout and lastButtonPress != 0:
            lastButtonPress = 0 # only handle button press once
            lastUpdate = now - updateInterval + 2000 # force update in 2s
            saveSettings()
            drawMenu(True)


init()
easydraw.msg("Fetching newest picture URL from API...")
run()