from flask import Blueprint, request, current_app
from flask import render_template, jsonify
from flask_socketio import emit
import sqlalchemy
import os
import json

from app.models.kitchen_model import Kitchen


from .. import db
from .. import socketio
from ..models.database.object_model import Object as DBObject
from ..models.database.kitchen_model import DBKitchen
from ..models.ticket_model import Ticket
from ..models.ticket_model import Ticket
from ..models.component_model import TicketStatus

bp = Blueprint("kds", __name__, url_prefix="/kds")


@bp.route("/", methods=["GET"])
def index(kitchenId=None):
    """
    A route to display the tickets to be prepared in the kitchen.
    """

    # Updating static/assets/assets/config.json
    configFilePath = os.path.join(
        current_app.config["BASE_DIR"], "app/static/assets/assets/", "config.json"
    )
    print(configFilePath)
    # Reading from json file
    with open(configFilePath, "r") as configFile:
        jsonObject = json.load(configFile)

    # Updating config
    jsonObject["ws-server"] = current_app.config["KDS_API_SERVER"]
    jsonObject["ws-port"] = current_app.config["KDS_API_PORT"]

    # Writing from json file
    with open(configFilePath, "w") as configFile:
        json.dump(jsonObject, configFile)

    return render_template("index.html")
    # return "OK"


@bp.route("/kitchen-create", methods=["POST"])
def kitchen_create():
    """
    TODO: Add definition ... .
    """

    kitchen = Kitchen()
    kitchen.from_json(request.json)
    kitchen.to_db()

    socketio.emit("kitchen-created", kitchen.to_json(), broadcast=True)

    return {}, 200


@bp.route("/kitchen-update", methods=["POST"])
def kitchen_update():
    """
    TODO: Add definition ... .
    """

    return {}, 400
    # if "id" in request.json:
    #     db_kitchen = (
    #         db.session.query(DBKitchen)
    #         .filter(DBKitchen.kth_kitchen_id == request.json["id"])
    #         .one()
    #     )
    #     if db_kitchen:
    #         db_kitchen.kth_kitchen = request.json["title"]

    # else:
    #     pass

    # kitchen = Kitchen()
    # kitchen.from_json(request.json)
    # kitchen.to_db()

    # socketio.emit("kitchen-updated", kitchen.to_json(), broadcast=True)

    # return {}, 200


@bp.route("/kitchen-get-all", methods=["GET"])
def kitchen_get_all():
    """
    TODO: Add definition ... .
    """

    kitchens = []
    db_kitchens = db.session.query(DBKitchen).all()
    for db_kitchen in db_kitchens:
        kitchen = Kitchen()
        kitchen.from_db(db_kitchen)
        kitchens.append(kitchen.to_json())

    return jsonify(kitchens)


@bp.route("/kitchen-do-reset", methods=["GET"])
def kitchen_do_reset():
    """
    TODO: Add definition ... .
    """

    db.session.begin()
    db.session.execute(sqlalchemy.delete(DBKitchen))
    db.session.execute("DELETE from main.sqlite_sequence where name = 'kds_kitchen'")
    db.session.commit()

    socketio.emit("kitchen-reset", {}, broadcast=True)

    return {}, 200


@bp.route("/mqtt", methods=["POST"])
def ticket_create():
    """
    TODO: Add definition ... .
    """

    ticket = Ticket()
    ticket.from_json(request.json)
    ticket.to_db()

    socketio.emit("ticket-ordered", ticket.to_json(), broadcast=True)

    return {}, 200


@bp.route("/ticket-get-all", methods=["GET"])
def ticket_get_all():
    """
    A route to display the current queue (of tickets).
    """

    tickets = []
    db_tickets = db.session.query(DBObject).filter(DBObject.obj_type == "Ticket").all()
    for db_ticket in db_tickets:
        ticket = Ticket()
        ticket.from_db(db_ticket)
        tickets.append(ticket.to_json())

    return jsonify(tickets)


@bp.route("/ticket-do-reset", methods=["GET"])
def ticket_do_reset():
    """
    A route to reste the current queue.
    """

    db.session.begin()
    db.session.execute(sqlalchemy.delete(DBObject))
    db.session.execute("DELETE from main.sqlite_sequence where name = 'kds_object'")
    db.session.commit()

    # socketio.emit("reset", {}, broadcast=True)
    socketio.emit("ticket-reset", {}, broadcast=True)

    return {}, 200


@socketio.on("connect")
def on_connect():
    """
    An event handler to ... .
    """
    print("Display [%s] connected!" % (request.sid))


@socketio.on("kitchen-get-all")
def on_kitchen_get_all():
    """
    An event handler to ... .
    """

    kitchens = []
    db_kitchens = db.session.query(DBKitchen).all()
    for db_kitchen in db_kitchens:
        kitchen = Kitchen()
        kitchen.from_db(db_kitchen)
        kitchens.append(kitchen.to_json())

    emit("kitchen-all", kitchens, broadcast=True)  # TODO: Remove ', broadcast=True'


@socketio.on("order-set-status")
def order_set_status(data):
    """
    TODO: Add definition ... .
    """

    print(data)
    print("Marking Order[%s] as %s" % (data["reference"], data["status"]))
    tickets = []
    db_tickets = (
        db.session.query(DBObject)
        .filter(DBObject.obj_reference == data["reference"])
        .all()
    )
    for db_ticket in db_tickets:
        ticket = Ticket()
        ticket.from_db(db_ticket)

        print("Marking Ticket[%d] as %s" % (ticket.id, data["status"]))
        db_ticket.obj_status = data["status"]
        ticket.status = data["status"]

        for item in ticket.items:
            db_item = (
                db.session.query(DBObject).filter(DBObject.obj_object_id == item.id).one()
            )
            print("Marking Item[%d] as %s" % (item.id, data["status"]))
            db_item.obj_status = data["status"]
            item.status = data["status"]

        tickets.append(ticket.to_json())

    db.session.commit()
    
    if data["status"] != str(TicketStatus.served):
        socketio.emit("ticket-updated", tickets, broadcast=True)
    else:
        socketio.emit("ticket-delete", tickets, broadcast=True)


@socketio.on("ticket-get-all")
def on_ticket_get_all():
    """
    An event handler to ... .
    """

    tickets = []
    db_tickets = (
        db.session.query(DBObject)
        .filter(DBObject.obj_type == "Ticket")
        .filter(DBObject.obj_status != str(TicketStatus.served))
        .all()
    )
    for db_ticket in db_tickets:
        ticket = Ticket()
        ticket.from_db(db_ticket)
        tickets.append(ticket.to_json())

    emit("ticket-all", tickets, broadcast=True)  # TODO: Remove ', broadcast=True'


@socketio.on("ticket-set-status")
def ticket_set_status(data):
    """
    TODO: Add definition ... .
    """

    print(data)
    ticket = Ticket()
    db_ticket = (
        db.session.query(DBObject).filter(DBObject.obj_object_id == data["id"]).one()
    )
    ticket.from_db(db_ticket)

    print("Marking Ticket[%d] as %s" % (data["id"], data["status"]))
    db_ticket.obj_status = data["status"]
    ticket.status = data["status"]

    for item in ticket.items:
        db_item = (
            db.session.query(DBObject).filter(DBObject.obj_object_id == item.id).one()
        )
        print("Marking Item[%d] as %s" % (item.id, data["status"]))
        db_item.obj_status = data["status"]
        item.status = data["status"]

    db.session.commit()
    socketio.emit("ticket-updated", [ticket.to_json()], broadcast=True)


@socketio.on("ticket-set-ticket-item-status")
def ticket_set_ticket_item_status(data):
    """
    TODO: Add definition ... .
    """

    print(data)
    print("Marking Item[%d] as %s" % (data["id"], data["status"]))
    db_item = (
        db.session.query(DBObject).filter(DBObject.obj_object_id == data["id"]).one()
    )
    db_item.obj_status = data["status"]
    db.session.commit()

    # Get the whole (and updated) Ticket from DB
    db_ticket = (
        db.session.query(DBObject)
        .filter(DBObject.obj_object_id == db_item.obj_parent_id)
        .one()
    )
    ticket = Ticket()
    ticket.from_db(db_ticket)
    socketio.emit("ticket-updated", [ticket.to_json()], broadcast=True)
