import myfab.log as log
from flask import Flask, request
from flask_jwt_extended import (
    JWTManager,
    jwt_required,
    create_refresh_token,
    get_raw_jwt,
    current_user,
)
from threading import Thread
import time
import traceback
import datetime
from myfab.model import (
    Event,
    PrintRequest,
    User,
    init_db_connection,
    Queue,
    QueueElement,
    Printer,
    PrinterQueue,
    Message,
)
from flask_api import status
from flask import jsonify
import string
import random
import os
import json
from flask_cors import CORS
from myfab.queue import (
    get_queues,
    remove_queue,
    enqueue,
    get_printers_from_db,
    get_printers,
    get_printer_by_name,
    get_printer_by_id,
    get_printers_for_queue,
    register_printer,
    get_queue_by_id,
    delete_printer,
    pull_printers,
    get_printer_for_request,
    get_queue_element_pos,
    get_queue_elements_list
)

init_db_connection()
log.info("Database connected")

app = Flask(__name__)
CORS(app)

JWT_PATH = (
    os.environ["JWT_PATH"] if "JWT_PATH" in os.environ else "/jwt_public.pem"
)
with open(JWT_PATH) as fh:
    app.config["JWT_PUBLIC_KEY"] = fh.read()

app.config['JSON_SORT_KEYS'] = False
app.config["JWT_ALGORITHM"] = "RS256"
app.config["JWT_IDENTITY_CLAIM"] = "login_name"
print(app.config["JWT_PUBLIC_KEY"])

FILE_SAVE_PATH = "/data"
os.makedirs(FILE_SAVE_PATH, exist_ok=True)

jwt = JWTManager(app)


@jwt.user_loader_callback_loader
def identity(payload):
    payload = get_raw_jwt()
    return get_or_create_user(
        payload["login_name"], payload["firstname"] + " " + payload["lastname"]
    )


log.info("Loaded JWT")

### ENUMS ###

REQUEST_STATUS_PENDING_REVIEW = 0  # initial state
REQUEST_STATUS_APPROVED = 1  # approved, waiting slicing
REQUEST_STATUS_AWAITING_PRINT = 2  # sliced, in print queue
REQUEST_STATUS_PRINTING = 3  # currently printing
REQUEST_STATUS_FINISHED = 4  # done printing, waiting for recuperation
REQUEST_STATUS_CLOSED = 5  # archived
REQUEST_STATUS_PICKED = 6  # object was picked up by client
REQUEST_STATUS_REJECTED = 10  # refused by operator
REQUEST_STATUS_PRINT_FAILED = 11  # print failed more than allowed
REQUEST_STATUS_STANDBY = 12  # on hold, from any state
REQUEST_STATUS_CANCELED = 13  # canceled

REQUEST_ACCESS_DENIED = 0  # Not allowed to see this request
REQUEST_ACCESS_OBSERVER = 1  # Allowed to see this request
REQUEST_ACCESS_USER = 2  # Is the author of this request
REQUEST_ACCESS_OPERATOR = 3  # Is an operator of the system

USER_ACCESS_NORMAL = 0
USER_ACCESS_OBSERVER = 1
USER_ACCESS_OPERATOR = 2

# Elements that can be modified by a user (not op)
REQUEST_USER_ELEMENTS = set(["title", "description", "project"])

# region UTILS
def get_or_create_user(username: str, fullname: str = None):
    req = User.select().where(User.username == username)
    if req.count():
        return req.get()
    else:
        if not fullname:
            raise Exception("fullname cannot be None")
        return User.create(username=username, fullname=fullname)


def lookup_requests(author: str = None, status=None, req_id=None):
    where_req = []
    if author:
        where_req.append(PrintRequest.author.username == author)

    if status and len(status) > 0:
        w = None
        for sts in status:
            if w is None:
                w = PrintRequest.status == sts
            else:
                w = w or PrintRequest.status == sts
        where_req.append(w)

    if req_id:
        where_req.append(PrintRequest.id == req_id)

    req = (
        PrintRequest.select()
        .join(User, on=(PrintRequest.author == User.username))
        .limit(200)
    )  # .join(Queue, on=(PrintRequest.queue == Queue.id))
    if len(where_req) > 0:
        req = req.where(*where_req)

    req = req.order_by(PrintRequest.last_modification.desc())
    return req


def get_request_by_id(rid):
    req = PrintRequest.select().where(PrintRequest.id == rid)
    return req.get() if req.count() else None


def add_request_event(req: PrintRequest, desc: str, op: User = None):
    log.info("Req %s: %s" % (req.id, desc))
    req.last_modification = datetime.datetime.now()
    req.save()
    Event.create(request=req, description=desc, operator=op)


def dequeue_apply(req: PrintRequest):
    if req.queue_element != None:
        req.queue_element.state = 3
        req.queue_element.save()
        req.queue_element = None
        req.save()

"""
Datetime to str
"""


def extract_date_time(elem):
    if type(elem) == tuple:
        elem = elem[0]
    # elem = datetime.datetime.fromisoformat(repr(elem))
    return (
        f"{elem.day}/{elem.month}/{elem.year} {elem.hour}:{elem.minute}:{elem.second}"
    )


def loop_requests(reqs):
    rqs = []
    # if type(reqs) != list:
    #     reqs = [reqs]
    for req in reqs:
        if get_access_level_to_request(req, current_user) == REQUEST_ACCESS_DENIED:
            continue
        p = get_printer_for_request(req)
        rqs.append(
            {
                "request_id": req.id,
                "title": req.title,
                "creation": extract_date_time(req.creation),
                "last_modification": extract_date_time(req.last_modification),
                "author": req.author.fullname,
                "description": req.description,
                "stl": req.stl,
                "status": req.status,
                "reject_message": req.reject_message,
                "project": req.project,
                "gcode": req.gcode,
                "operator": req.operator.username if req.operator is not None else None,
                "queue": req.queue_element.queue.id if req.queue_element is not None else None,
                "queue_position": get_queue_element_pos(req.queue_element) if req.queue_element is not None else -1,
                "recup": req.recup_id,
                "progress": p.printer_state["job"] if p != None else None
            }
        )
    return rqs


def get_access_level_to_request(req: PrintRequest, user):
    # req is id or req same for user
    if req is not PrintRequest:
        req = get_request_by_id(req)
        if req is None:
            raise Exception("No such request")
    if user is not User:
        user = get_or_create_user(user)

    if user.access == USER_ACCESS_OPERATOR:
        return REQUEST_ACCESS_OPERATOR  # user is admin
    if user.access == USER_ACCESS_OBSERVER:
        return REQUEST_ACCESS_OBSERVER  # user has unlimited view
    if user.access == USER_ACCESS_NORMAL:
        if req.author == user:
            return REQUEST_ACCESS_USER  # user is creator of the request
        else:
            return REQUEST_ACCESS_DENIED  # user does not have access


def update_requires_operator_rights(update_json):
    s = set(update_json)
    s.discard(REQUEST_USER_ELEMENTS)
    return len(s) > 0


# endregion UTILS

# region routes

# region Project management & basic routes


@app.route("/whoami")
@jwt_required
def whoami():
    return jsonify(
        {
            "username": current_user.username,
            "fullname": current_user.fullname,
            "access": current_user.access,
        }
    )


@app.route("/requests/my")
@jwt_required
def get_my_requests():
    return jsonify(loop_requests(lookup_requests(current_user.username)))

@app.route("/requests/<req_id>/dequeue")
@jwt_required
def dequeue_request(req_id):
    req: PrintRequest = get_request_by_id(req_id)
    if req is None:
        return jsonify({"error": "No such request"}), status.HTTP_404_NOT_FOUND

    if req.queue_element == None:
        return jsonify({"error": "Not queued"}), status.HTTP_404_NOT_FOUND

    dequeue_apply(req)
    return jsonify({})

@app.route("/requests/<req_id>", methods=["PUT"])
@jwt_required
def update_request(req_id):
    # Author can update request initial parameters when status is 0
    # Operator can update all request parameters
    #

    req: PrintRequest = get_request_by_id(req_id)
    changes = request.get_json()
    if not changes:
        return jsonify({"error": "No modifications"}), status.HTTP_400_BAD_REQUEST
    if req is None:
        return jsonify({"error": "No such request"}), status.HTTP_404_NOT_FOUND

    required_access = (
        REQUEST_ACCESS_OPERATOR
        if req.status > 0 or update_requires_operator_rights(changes)
        else REQUEST_ACCESS_USER
    )

    if get_access_level_to_request(req, current_user) < required_access:
        return jsonify({"error": "Access denied"}), status.HTTP_401_UNAUTHORIZED

    # TODO V3: request statistics
    for e in changes:
        if e == "status":
            if changes[e] == REQUEST_STATUS_CLOSED:
                # Dequeue request on close
                dequeue_apply(req)
        setattr(req, e, changes[e])
    req.last_modification = datetime.datetime.now()
    req.save()
    return jsonify({})

@app.route("/requests/<req_id>/enqueue/<qid>")
@jwt_required
def add_request(req_id, qid):
    req = get_request_by_id(req_id)
    if not req:
        return jsonify({"error": "No such request"}), status.HTTP_404_NOT_FOUND
    queue = get_queue_by_id(qid)
    if not queue:
        return jsonify({'error': 'No such queue'}), status.HTTP_404_NOT_FOUND
    if req.queue_element != None:
        req.queue_element.state = 3 # cancel this
        req.queue_element.save()
        req.queue_element = None # delete queue element in the request
        req.save()

    enqueue(req, queue)
    return jsonify({})

# @app.route("/requests/<req_id>")

@app.route("/requests/new", methods=["POST"])
@jwt_required
def add_new_request():
    data = request.get_json()
    if not "title" in data or data["title"] == "":
        return jsonify({"error": "Title field required"}), status.HTTP_404_NOT_FOUND
    if not "description" in data or data["description"] == "":
        return (
            jsonify({"error": "Description field is required"}),
            status.HTTP_404_NOT_FOUND,
        )
    if not "project" in data or data["project"] == "":
        return (
            jsonify({"error": "Project field is required"}),
            status.HTTP_404_NOT_FOUND,
        )

    recup = "".join([random.choice(string.ascii_letters + string.digits) for n in range(5)]).upper()

    req = PrintRequest.create(
        title=data["title"],
        description=data["description"],
        author=current_user,
        project=data["project"],
        recup_id=recup
    )
    log.info(
        "Created print request '%s' by user %s (%s)"
        % (req.title, current_user.username, current_user.fullname)
    )
    add_request_event(req, "Request created")

    return jsonify({"request_id": req.id})


@app.route("/files/<kind>/upload/<req_id>", methods=["POST"])
@jwt_required
def stl_upload(kind, req_id):
    if not kind in ["stl", "gcode"]:
        return jsonify({"error": "Invalid file kind"}, status.HTTP_400_BAD_REQUEST)

    req: PrintRequest = get_request_by_id(int(req_id))
    if req == None:
        return jsonify({"error": "No such print request"}), status.HTTP_404_NOT_FOUND
    required_access = REQUEST_ACCESS_USER if kind == "stl" else REQUEST_ACCESS_OPERATOR

    access = get_access_level_to_request(req_id, current_user)
    if access < required_access:
        log.warn(f'Access denied for user {current_user.username} to request {req_id} access is {access}')
        return jsonify({"error": "Access denied"}),  status.HTTP_401_UNAUTHORIZED
    file = request.files["file"]
    if file.filename == "":
        return jsonify({"error": "No file"}, status.HTTP_400_BAD_REQUEST)

    name = "".join(
        [random.choice(string.ascii_letters + string.digits) for n in range(64)]
    )
    name = name + "." + kind

    if kind == "stl":
        req.stl = name
    elif kind == "gcode":
        req.gcode = name
        req.status = REQUEST_STATUS_AWAITING_PRINT
    else:
        return jsonify({"error": "Invalid file kind"}, status.HTTP_400_BAD_REQUEST)

    file.save(os.path.join(FILE_SAVE_PATH, name))
    req.save()
    add_request_event(req, f"Added {kind} file")

    return jsonify({"ok": True})


@app.route("/requests/<req_id>")
@jwt_required
def get_request_infos(req_id):
    return jsonify(
        loop_requests(lookup_requests(req_id=req_id))
    )  # ! FIXME Don't get request if no access


@app.route("/requests/list", methods=["POST"])
@jwt_required
def get_requests():  #! FIXME Don't get request if not access
    params = request.get_json()
    if not "username" in params:
        params["username"] = None
    if not "status" in params:
        params["status"] = None
    if not "limit" in params:
        params["limit"] = 20
    return jsonify(loop_requests(lookup_requests(params["username"], params["status"])))


# endregion

# region user management routes

# user list
@app.route("/users")
@jwt_required
def list_users():
    if current_user.access != USER_ACCESS_OPERATOR:
        return jsonify({"error": "Access denied"}), status.HTTP_401_UNAUTHORIZED
    users = []
    for user in User.select():
        users.append(
            {
                "username": user.username,
                "fullname": user.fullname,
                "access": user.access,
            }
        )

    return jsonify(users)


# change user TODO
@app.route("/users/<username>", methods=["PUT"])
@jwt_required
def update_user(username):
    if current_user.access != USER_ACCESS_OPERATOR:
        return jsonify({"error": "Access Denied"}), status.HTTP_401_UNAUTHORIZED
    user = get_or_create_user(username)  # FIXME no such user is 500
    changes = request.get_json()

    for e in changes:
        setattr(user, e, changes[e])

    user.save()
    return jsonify({})


# endregion user management

# region Message system routes


@app.route("/message/<request_id>")
@jwt_required
def get_messages(request_id):
    messages = []
    req = get_request_by_id(request_id)
    if req == None:
        return jsonify({"error": "No such request"}), status.HTTP_404_NOT_FOUND
    if get_access_level_to_request(req, current_user) < REQUEST_ACCESS_OBSERVER:
        return jsonify({"error": "Access Denied"}), status.HTTP_401_UNAUTHORIZED
    for msg in (
        Message.select()
        .where(Message.request == req)
        .order_by(Message.id)
        .desc()
        .limit(30)
    ):
        messages.append(
            {
                "req": msg.request.id,
                "author": msg.author.fullname,
                "text": msg,
                "creation": msg.creation,
                "id": msg.id,
                "read": msg.read,
            }
        )
        if msg.author != current_user:
            msg.read = True
            msg.save()
    return jsonify(messages)


@app.route("/message/<request_id>", methods=["POST"])
@jwt_required
def post_message(request_id):
    data = request.get_json()
    req = get_request_by_id(request_id)
    if not req:
        return jsonify({"error": "No such request"}), status.HTTP_404_NOT_FOUND
    Message.create(request=req, text=data["message"], author=current_user)
    return jsonify({})


# @app.route("/message/unread")
# @jwt_required
# def unread_messages():
#     messages = []
#     for msg in Message.select().where(
#         Message.request.author == current_user and Message.read == False
#     ):
#         messages.append(
#             {
#                 "req": msg.request.id,
#                 "author": msg.author.fullname,
#                 "text": msg,
#                 "creation": msg.creation,
#                 "id": msg.id,
#             }
#         )


# endregion

# region printer management routes

# list printers & status
def serialize_current_print(pr: PrintRequest):
    return {
        'id': pr.id,
        'author': pr.author.fullname,
        'title': pr.title
    }


@app.route("/printers")
@jwt_required
def list_printers():
    """
    [
        {
            "id": "generated_id",
            "name": "given name by operators",
            "current_print": null,
            "version": "octoprint & dfpm",
            "printer_type": "mini_prusa_mk3",
            "status": "printing, idle, error, out of commission, virtual printer...",
            "print_progress": 0.0, or -1 if not printing
            "infos": {temperatures etc...}
            "remaining_print_time": seconds
            "ready_state": bool, ready to accept print
            "clear_plate_flag": bool, True: pls confirm plate is clear
            "enabled": bool, is the printer enabled false: out of commission
            "meta": object,
            "queues": [Queue]
        }
    ]
    """
    printers = []
    for printer in get_printers():
        req, queue = printer._get_next_print()
        next_print = {
            'request': {
                'id': req.id,
                'title': req.title,
                'author': req.author.fullname,
                'description': req.description,
            },
            'queue': {
                'id': queue.id
            }
        } if req != None else None
        printers.append(
            {
                "id": printer.id,
                "name": printer.name,
                "current_print": serialize_current_print(printer.current_print) if printer.current_print != None else None,
                "version": printer.version(),
                "printer_type": printer.printer_type(),
                "status": printer.status(),
                "printer_progress": printer.print_progress(),
                "infos": printer.infos(),
                "remaining_print_time": printer.remaining_print_time(),
                "ready_state": printer.ready_state,
                "clear_plate_flag": printer.clear_plate_flag,
                "enabled": printer.enabled,
                "config": printer.config,
                "queues": printer.serialized_queues(),
                'next_print': next_print
            }
        )
    return jsonify(printers)

@app.route("/printers/<printer_id>/clear/<value>")
@jwt_required
def plate_cleared(printer_id, value):
    if request.method == "GET":
        p = get_printer_by_id(printer_id)
        if p == None:
            return jsonify({'error': 'No such printer'}), status.HTTP_404_NOT_FOUND
        p.set_plate_clear_flag(bool(int(value)))
        return jsonify({})

@app.route("/printers/<printer_id>/print_result/<result>")
@jwt_required
def print_result(printer_id, result):
    p = get_printer_by_id(printer_id)
    if p == None:
        return jsonify({'error': 'No such printer'}), status.HTTP_404_NOT_FOUND
    p.reset_current_print(int(result))
    return jsonify({})

# action on printer TODO v2
@app.route("/printers/<printer_id>/action/<action>", methods=["GET"])
@jwt_required
def action_printer(printer_id, action):
    """
    {
        "action": "toggle", "cancel", "cycle", "toggle_enabled", "restart"
    }
    toggle cancel are self explainatory
    cycle: goes to the next file in queue, implies no print job is running. Display a warn message first
    disable: put printer out of commission (disconnect serial port)
    enable: reconnect serial port
    """
    p = get_printer_by_id(printer_id)
    if action == "toggle":
        p.toggle_pause()
    elif action == "cancel":
        p.cancel_print()
    elif action == "cycle":
        p.cycle_print()
    elif action == "toggle_enabled":
        p.toggle()
    else:
        jsonify(
            {"error": f"Action {action} is not allowed"}
        ), status.HTTP_405_METHOD_NOT_ALLOWED
    return jsonify({})

# @app.route("/printers/<printer_id>/next_print")
# @jwt_required
# def get_next_print(printer_id):
#     printer = get_printer_by_id(printer_id)
#     if not printer:
#         return jsonify({"error": "No such printer"}), status.HTTP_404_NOT_FOUND
#     req, queue = printer._get_next_print()
#     if req != None:
#         return jsonify({
#             'request': {
#                 'id': req.id,
#                 'title': req.title,
#                 'author': req.author.fullname,
#                 'description': req.description,
#             },
#             'queue': {
#                 'id': queue.id
#             }
#         })
#     else:
#         return jsonify({})

# Edit printer config except queues
@app.route("/printers/<printer_id>", methods=["PUT"])
@jwt_required
def update_printer(printer_id):
    printer = get_printer_by_id(printer_id)
    if not printer:
        return jsonify({"error": "No such printer"}), status.HTTP_404_NOT_FOUND
    printer_update = request.get_json()
    for elem in printer_update:
        setattr(printer.printer_obj, elem, printer_update[elem])
    printer.printer_obj.save()
    return jsonify({})

@app.route("/printers/<printer_id>/queue/<qid>", methods=["PUT", "DELETE"])
@jwt_required
def printer_queue(printer_id, qid):
    printer = get_printer_by_id(printer_id)
    if not printer:
        return jsonify({"error": "No such priner"}), status.HTTP_404_NOT_FOUND
    queue = get_queue_by_id(qid)
    if not queue:
        return jsonify({"error": "No such queue"}), status.HTTP_404_NOT_FOUND

    if request.method == "PUT":
        for q in printer.queues:
            if q.id == int(qid):
                return (
                    jsonify({"error": "Printer already attached to this queue"}),
                    status.HTTP_409_CONFLICT,
                )
        PrinterQueue.create(printer=printer.printer_obj, queue=queue)
        printer.load_queues()
        return jsonify({})
    else:
        # for q in printer.queues:
        #     if q.id == qid:
        PrinterQueue.delete().where(
            PrinterQueue.printer == printer.printer_obj and PrinterQueue.queue == queue
        ).execute()
        printer.load_queues()
        return jsonify({})
       


# Add printer config
@app.route("/printers", methods=["POST"])
@jwt_required
def add_new_printer():
    printer_info = request.get_json()
    Printer.create(
        name=printer_info["name"],
        model=printer_info["model"],
        config=printer_info["config"],
    )
    return jsonify({})



@app.route("/printers/announce/<name>/<key>")
def announce_printer(name, key):    
    ip = request.environ['REMOTE_ADDR'] if request.environ.get('HTTP_X_FORWARDED_FOR') is None else request.environ['HTTP_X_FORWARDED_FOR']
    cfg = json.dumps({"hostname": ip, "port": 5000, "key": key})
    log.info(f'Registring printer {name} with config {cfg}')
    printer = get_printer_by_name(name)
    if printer == None:
        register_printer(Printer.create(name=name, model="octoprint", config=cfg))
        return jsonify({})
    printer.printer_obj.config = cfg
    printer.printer_obj.save()
    printer.reload_printer_connection_settings()
    printer._refresh_printer_status()
    return jsonify({})


@app.route("/printers/<id>/home")
@jwt_required
def home_printer(id):
    p = get_printer_by_id(id)
    if p == None:
        return jsonify({'error': 'No such printer'}), status.HTTP_404_NOT_FOUND
    if not p.accept_control:
        return jsonify({'error': 'Printer is not ready to go home'}), status.HTTP_409_CONFLICT
    p.goto_home()
    return jsonify({})

@app.route("/printers/home_all")
@jwt_required
def home_all():
    for p in get_printers():
        if p.printer_model() == "octoprint" and p.accept_control:
            p.goto_home()
    return jsonify({})


@app.route("/printers/<printer_id>", methods=["DELETE"])
@jwt_required
def remove_printer(printer_id):
    # TODO check access level
    delete_printer(printer_id)
    return jsonify({})


# endregion printer management

# region queues management routes

# list queues
@app.route("/queues", methods=["GET", "POST"])
@jwt_required
def manage_queues():
    """
    [
        {
            "id": "id",
            "name": "queue_name",
            "weight": 0, queue weight,
            "printers": [ids ],*
            "enabled": true,
            "elements": [
                {PrintRequest}...
            ]
        }
    ]
    """
    if request.method == "GET":
        # get queues
        qs = []
        for q in get_queues():
            elems = get_queue_elements_list(q.id)
            qs.append(
                {
                    "id": q.id,
                    "name": q.name,
                    "weight": q.weight,
                    "printers": list(map(
                        lambda p: {"id": p.id, "name": p.name},
                        get_printers_for_queue(q),
                    )),
                    "enabled": q.enabled,
                    "elements": elems
                }
            )
        return jsonify(qs)
    elif request.method == "POST":
        # create new queue
        queue_info = request.get_json()
        Queue.create(
            enabled=True,
            name=queue_info["name"],
            weight=queue_info["weight"],
            meta=queue_info["meta"],
        )
        return jsonify({})
    else:
        return (
            jsonify({"error": "Method not allowed"}),
            status.HTTP_405_METHOD_NOT_ALLOWED,
        )


@app.route("/queues/<qid>", methods=["DELETE", "PUT"])
@jwt_required
def manage_queues_with_id(qid):
    queue = get_queue_by_id(qid)
    if queue == None:
        return jsonify({'error': 'No such queue'}), status.HTTP_404_NOT_FOUND
    if request.method == "DELETE":
        remove_queue(qid)
        return jsonify({})
    elif request.method == "PUT":
        # update queue info
        update = request.get_json()
        for elem in update:
            setattr(queue, elem, update[elem])
        queue.save()
        #Queue.update(request.get_json()).where(Queue.id == qid)
        return jsonify(request.get_json())
    else:
        return (
            jsonify({"error": "Method not allowed"}),
            status.HTTP_405_METHOD_NOT_ALLOWED,
        )


# endregion queues

# region slicer manager routes TODO

"""
GET /slicer/update
Authorization: Slicer key
{
    "slicer_id",
}

200 OK
{
    "print_id"
    "title",
    "operator_name"
    "upload_token"
}

-------
 
POST /slicer/usage
{
    ??? infos & crash status
}

"""

# endregion slicer

# endregion routes

# region startup code

pull_printers()


def update_printer(p):
    if p.printer_model() == "octoprint":
        p.cycle_print()

def update_printers():
    log.info("Refreshing printers")
    for p in get_printers():
        try:
            update_printer(p)
        except:
            traceback.print_exc()

def recurrent_printer_update():
    while True:
        time.sleep(5)
        try:
            update_printers()
        except:
            traceback.print_exc()

Thread(target=recurrent_printer_update, name="Printer Update Thread", daemon=True, args=()).start()

# endregion startup code

# peewee usage

# user = User.select().where(User.username == "test").count()
# print(user)
# print("fin")

# if user:
#     User.delete_by_id("test")
# #User.create(username="test", fullname="test TEST")
# user = User.select().where(User.username == "test").count()
# print(user)

# for user in User.select().where(User.username == "test"):
#     print(user)
# print("fin")
