from pyscript import WebSocket, fetch, display
import asyncio
from js import document, console, setInterval, window
import js
from js import setTimeout, clearTimeout
from datetime import datetime
import io
import base64
import json
import time
import re
from pyodide.ffi import create_proxy



NOT_FOUND: str = '***'
API_SYS: str = '/api/v3/sys'
LOCAL_DATA = {}
INFO_ERROR = 'InfoError'



##################################
# timer
timeout_id = None


def hidePanelInfo(event=None):
    # console.log('hidePanelInfo')
    ID('panelInfo').innerHTML = ''
    ID('panelInfo').classList.remove('notifica')


def reset_timer(event=None):
    global timeout_id
    # console.log('reset_timer')
    if timeout_id is not None:
        clearTimeout(timeout_id)
    timeout_id = setTimeout(create_proxy(hidePanelInfo), 5000)


##################################

def pp(data: dict) -> str:
    ret = ''
    console.log(type(data))
    for i in data:
        console.log(i, type(data[i]))
        if isinstance(data[i], dict):
            console.log(f'{i}:>> DICT')
            # ret += f"{i}: {pp(data[i])}\n"
            # continue
        ret += f"{i}: {data[i]}\n"
    return ret

def confirm(message):
    return window.confirm(message)

def updateInfo(data):
    ma = ID('panelInfo')
    # ma.classList.remove('notifica')
    # ma.classList.remove('is-success')
    # ma.classList.remove('is-warning')
    # ma.classList.remove('is-danger')
    # ma.innerHTML = ''
    # if 'status' in data:
    #     if data['status']:
    #         ma.classList.add('is-success')
    #     else:
    #         ma.classList.add('is-danger')

    if 'message' in data:
        ma.classList.add('notifica')
        ma.innerHTML += '<br>' if ma.innerHTML else ''
        ma.innerHTML += data['message']
        reset_timer()


def loadFiles(data):
    if 'type' in data:
        # se nel response, c'è una lista allora scarico tutta la lista.
        files = [data['id'],] if isinstance(data['id'], str) else data['id']
        for file in files:
            api = f'''/api/v3/{data['type']}/{file}'''
            # console.log('SCARICO', file, api)
            window.open(api)
            # time.sleep(1)


async def GET(url, params: dict = {}, timeout=60):
    data = await make_request(url, 'GET', params)
    updateInfo(data)
    return data


async def POST(url, data: dict = {}, timeout=60):
    # import json
    # data = json.dumps(data)
    data = await make_request(url, 'POST', data)
    updateInfo(data)
    return data


async def make_request(url, method, data: dict = None, timeout=60):
    ID('waitModal').classList.add('visible')

    headers = {
        'X-Requested-With': 'XMLHttpRequest',
        'Content-Type': 'application/json',
    }
    params = {
        'url': url,
        'method': method,
        'headers': headers,
        'timeout': timeout,
    }
    if method == 'GET' and isinstance(data, dict):
        p = ''
        for param in data:
            sep = '&'if p else '?'
            p += f"{sep}{param}={data[param]}"
        params['url'] += p
    if method == 'POST' and isinstance(data, dict):
        params['body'] = json.dumps(data)
    resp = await fetch(
        **params)

    if resp.ok:
        data = {}
        dataR = await resp.json()
        for i in dataR:
            data[i] = dataR[i]

    ID('waitModal').classList.remove('visible')
    loadFiles(data)

    return data


# def readKeyence():
#     import socket
#     val = ''
#     host = '192.168.12.221'
#     port =9004
#     addr = socket.getaddrinfo(host=host, port=port)[0][-1]
#     s = socket.socket()
#     s.connect(addr)
#     s.send('LON\n')
#     while True:
#         data = s.recv(100)
#         if data:
#             val = data
#             console.log(data)
#         else:
#             break
#     s.close()
#     return val

def ID(id):
    return document.getElementById(id)


def ClassID(id):
    return document.getElementsByClassName(id)


def getValues(classname: str = 'inputdata'):
    ret = {}
    for f in document.getElementsByClassName(classname):
        # console.log(f.id)
        if f.type == 'checkbox':
            ret[f.id] = f.checked
        else:
            ret[f.id] = f.value.strip()
    return ret


def clearValues(classname: str = 'inputdata'):
    for f in document.getElementsByClassName(classname):
        if f.id != 'prn':
            if f.type == 'checkbox':
                f.checked = False
            else:
                f.value = ''


def setValues(data: dict):
    for element in data:
        ele = ID(element)
        val = data[element]
        # print(element, val)
        if ele:
            if ele.type == 'checkbox':
                ele.checked = val
            else:
                ele.value = val


def setOnEvent(element, func, event='click'):
    ele = document.getElementById(element)
    ele.addEventListener(event, create_proxy(func))


def setClassOnEvent(classname, func, event='click'):
    # console.log('setClassOnEvent', classname, func, event)
    for ele in ClassID(classname):
        ele.addEventListener(event, create_proxy(func))



def sendEvent(element, event='click'):
    # ele = document.getElementsByClassName(element)
    if isinstance(element, str):
        element = document.getElementById(element)
    if event == 'click': 
        eve = window.MouseEvent.new('click',{
            'view': window,
            'bubbles': True,
            'cancelable': True
        })
    elif event in ('keyup', 'keydown', 'keypress'):
        eve = window.KeyboardEvent.new(event,{
            'view': window,
            'bubbles': True,
            'cancelable': True
        })
    elif event == 'change':
        eve = window.Event.new('change',{
            'view': window,
            'bubbles': True,
            'cancelable': True
        })
    else:
        eve = window.Event.new(event,{
            'view': window,
            'bubbles': True,
            'cancelable': True
        })
    element.dispatchEvent(eve)


def setHTML(element, html):
    ele = document.getElementById(element)
    ele.innerHTML = html


def getField(data: dict, field: str) -> str:
    if field in data:
        return data[field]
    else:
        return ''


async def load(k):
    # for l in LOCAL_DATA:
    #     console.log('LOCAL_DATA', l, LOCAL_DATA[l])
    data = {'k': k}
    rep = await GET(API_SYS, data)
    h = rep['data']
    if not isinstance(h, (list, tuple)):
        h = [h, ]
    for hp in h:
        # console.log(hp['parent'], hp['html'])
        setHTML(hp['parent'], hp['html'])
        if 'title' in hp and hp['title']:
            document.title = hp['title']
            ID('idMenuTITLE').innerHTML = hp['title']
        if 'script' in hp and hp['script']:
            # console.log('SCRIPT:')
            # console.log(hp['script'])
            exec(hp['script'])
            # pyodide.eval_code(hp['script'])
    # if bc := ClassID('barcode'):
    #     value = readKeyence()
    #     if value:
    #         for ele in bc:
    #             bc.value = value


async def onMenu(e):
    await load('index.menu')
    # await load('test888')


# async def loadETI(e):
#     await load('eti')


def closeModal(e):
    modal = ClassIDID('modal')
    for m in modal:
        m.style.display = 'none'


curPanel = 0


async def loadImg(id):
    '''
        NON è possibile usare la GET in quanto ritorna i dati in formato json
    '''
    data = {'id': id}
    # console.log(f'loadImg>>{{data}}')

    img = await GET_img(f'/api/v3/image', data)
    # console.log(img)
    img = 'data:image/jpg;base64,'+img
    ID(id).src = img


async def CheckLogedIn():
    if ID('LogedInUsername').innerText != 'Login':
        ck = document.cookie
        utc = datetime.utcnow()
        ID('LogedInUsername').innerText = ck
        # console.log(utc, ck)
        # for s in ck:
        # console.log(utc, s)
        # data = await GET(f'/api/v3/islogedin')
        # if data and data['status']:
        #     console.log('ancora dentro')
        # else:
        #     ID('LogedInUsername').innerText = 'Login'
        #     await load('login')


def SetTimers():
    p_logedIn = pyodide.create_proxy(CheckLogedIn)
    t_logedIn = setInterval(p_logedIn, 60*1000)


def IDHide(id):
    ID(id).classList.add('hide')


def IDShow(id):
    ID(id).classList.remove('hide')


def panel(n: int):
    curPanel = n
    if n == 1:  # visualizza il menu
        ID('idMenuTITLE').innerHTML = 'Menu Principale'
    # panel 0 sempre visibile
    for i in range(1, 5):
        if (i == n):
            IDShow(f'panel{i}')
        else:
            IDHide(f'panel{i}')


async def logOut(e):
    await POST(f'/api/v3/logout')
    ID('panel0').innerHTML = ''
    await load('login')
    ID('LogedInUsername').innerText = 'LOGIN'


async def LogedIN(data):
    global LOCAL_DATA
    await load('index.menu')
    if 'username' in data:
        ID('LogedInUsername').innerText = data['username']
    if 'printers' in data:
        # console.log('AGGIUNTE STAMPANTI')
        LOCAL_DATA['printers'] = data['printers']


async def main():
    data = await GET(f'/api/v3/islogedin')

    if data and data['status']:
        await LogedIN(data['data'])
    else:
        await load('login')
    setOnEvent('LogedInUsername', logOut)


def onOpen(e):
    console.log('onOpen', e.type, e.data)
    ws.send('hello')


def onClose(e):
    console.log('onClose', e.type)


def onMessage(e):
    console.log('onMessage', e.type, e.data)
    # ws.close()


# ws = WebSocket(url='ws://localhost:5000/socket.io')
# ws.onopen = onOpen
# ws.onclose = onClose
# ws.onmessage = onMessage

await main()
