import badge, easywifi, network, ugfx, easydraw, sys, json, time, gc, deepsleep
import usocket as socket
import uselect

badge.init()
ugfx.init()

ugfx.set_lut(ugfx.LUT_FASTER)
ugfx.clear(ugfx.WHITE)

font = 'Terminus14'
with open('%s/shittyterm/%s.json' % (sys.path[1], font), 'r') as f:
    ugfx.fonts_load(json.loads(f.read()))
f.close()
gc.collect()


easywifi.enable(False)
if easywifi.state==False:
    easydraw.msg("Unable to connect to network!","FAILURE")
    easydraw.msg("Waiting 5 seconds to try again!")
    badge.eink_busy_wait()
    deepsleep.start_sleeping(5000)

termSize = [37, 8]
lineHeight = int(ugfx.height()/termSize[1])
buf = [" " * termSize[0] for i in range(termSize[1])]
cursor = [0, 0]

doFlush = True
lastFlush = 0;

def flushDisplay():
    global doFlush, lastFlush

    if time.ticks_diff(time.ticks_ms(), lastFlush) >= 750:
        doFlush = True

    if doFlush:
        badge.eink_busy_wait()
        ugfx.flush(ugfx.LUT_FASTER)
        lastFlush = time.ticks_ms()
    doFlush = False

def drawDisplay():
    ugfx.clear(ugfx.WHITE)
    for i in range(len(buf)):
        ugfx.string(0, lineHeight * i, buf[i], font, ugfx.BLACK)
    flushDisplay()

def resetTerm():
    global buf, cursor
    buf = [" " * termSize[0] for i in range(termSize[1])]
    ugfx.clear(ugfx.WHITE)
    badge.eink_busy_wait()
    ugfx.flush(ugfx.LUT_FULL)
    cursor = [0,0]

def rowDown():
    global buf, cursor
    row = cursor[1] + 1
    col = 0
    if row >= termSize[1]: # scroll down
        row = termSize[1] - 1
        buf.pop(0)
        buf.append(" " * termSize[0])    
    return [col, row]

def setChar(charIn, cl):
    global buf, cursor, doFlush
    [col, row] = cursor

    if ord(charIn) == 13: # CR
        col = 0
    elif ord(charIn) == 10: # NL
        [col, row] = rowDown()
        doFlush = True
    elif ord(charIn) == 8: # BS
        col = col - 1
    elif ord(charIn) == 7: # BEL
        ugfx.clear(ugfx.BLACK)
        ugfx.flush(ugfx.LUT_FASTER)
        doFlush = True
        drawDisplay()
    elif ord(charIn) == 27: # ESC
        c = ord(cl.read(1).decode("utf-8"))
        if c == 91: # [ (CSI)
            c = ord(cl.read(1).decode("utf-8"))
            if c == 72: # H, cursor to 0,0
                col = 0
                row = 0
            elif c == 75: # K, erase line
                buf[row] = buf[row][:col] + (" " * (termSize[0] - col))
            elif c == 50: # 2
                c = ord(cl.read(1).decode("utf-8"))
                if c == 74: # J, clear entire screen
                    cursBackup = cursor
                    resetTerm()
                    cursor = cursBackup
        elif c == 93: # ], start of ESC ] 0 ; txt ST Set icon name and window title to txt.
            c = cl.read(2).decode("utf-8")
            if ord(c[0]) == 48 and ord(c[1]) == 59:
                while c != 7:
                    c = ord(cl.read(1).decode("utf-8"))
            #col = ord(c[1]) - 48          
    elif ord(charIn) < 32 or ord(charIn) > 126: # all other non-characters
        pass # ignore    
    else:
        buf[row] = buf[row][:col] + charIn + buf[row][col+1:]
        print(charIn, end='')
        col = col + 1
        if row >= termSize[1]:
            row = 0
        if col >= termSize[0]:
            [col, row] = rowDown()
            doFlush = True
       
    cursor = [col, row]

    drawDisplay()

ip = network.WLAN(network.STA_IF).ifconfig()[0]
print("Connected, my IP address is " + ip)
easydraw.msg("Connected, my IP address is " + ip,"shittyterm")

addr = socket.getaddrinfo("0.0.0.0",1337)[0][-1]
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)
s.bind(addr)

s.listen(1)
s.settimeout(None)
print("Socket opened on port 1337")
easydraw.msg("Listening on port 1337..")

poll = uselect.poll()

doRun = True
while doRun:
    cl, remote_addr = s.accept()
    cl.settimeout(None)

    resetTerm()

    poll.register(cl, uselect.POLLIN)

    try:
        while True:
            res = poll.poll(750)
            if not res:
                # No new input
                doFlush = True
                flushDisplay()
            else:
                data = cl.read(1).decode("utf-8")
                if len(data) <= 0:
                    print("Client disappeared")
                    break
                setChar(data, cl)
                gc.collect()

    except Exception as err:
        print(err)
        doFlush = True
        flushDisplay()
    finally:
        poll.unregister(cl)
        cl.close()
        cl = None
        resetTerm()

s.close()