from flask import Flask
from flask_cors import CORS
from flask import request
from lxml import etree
import json
import time
import Parser


app = Flask(__name__)
CORS(app)
cors = CORS(app, resource={
    r"/*":{
        "origins":"*"
    }
})

def process_xml(request: request, type: str) -> str:
    """Function to process 

    :param request: Received request
    :param type: Type of needed processing: xsd, xslt or xpath
    :raises ValueError: is raised when type is different than those provided above
    :return: response JSON converted to string and response code
    """
    start = time.time_ns()
    code = 200
    response_json = dict()
    try:
        request_data = json.loads(request.get_data(as_text=True))
        data = request_data['data']
        process = request_data['process']
        if (type == "xsd"):
            response_json['result'] = Parser.xsd(data, process)
        elif (type == "xslt"):
            response_json['result'] = Parser.xslt(data, process)
        elif (type == "xpath"):
            response_json['result'], response_json['type'] = Parser.xpath(data, process)
        elif (type == "prettify"):
            response_json['result'] = Parser.formatXML(data, True)
        elif (type == "minimize"):
            response_json['result'] = Parser.formatXML(data, False)
        else:
            raise ValueError("Valid operation types are: xsd, xslt, xpath")

        response_json['status'] = "OK"
    except KeyError as e:
        response_json['result'] = "Missing key: " + str(e)
        response_json['status'] = "ERR"
        code = 400
    except Exception as e:
        response_json['result'] = str(e)
        response_json['status'] = "ERR"
        code = 400
    finally:
        exec_time = (time.time_ns() - start) / 10**6
        response_json['time'] = f"{exec_time:.03f}"
        response_json['processor'] = "libxml2 over lxml"
        return json.dumps(response_json), code


@app.route("/xpath", methods=["POST"])
def xpath():
    return process_xml(request, "xpath")

@app.route("/xsd", methods=["POST"])
def xsd():
    return process_xml(request, "xsd")

@app.route("/xslt", methods=["POST"])
def xslt():
    return process_xml(request, "xslt")

@app.route("/prettify", methods=["POST"])
def prettify():
    return process_xml(request, "prettify")

@app.route("/minimize", methods=["POST"])
def minimize():
    return process_xml(request, "minimize")

if __name__ == "__main__":
    app.run()