package com.r11.tools.controller;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.r11.tools.controller.internal.*;
import com.r11.tools.xml.Saxon;
import com.r11.tools.xml.Xalan;
import org.apache.logging.log4j.Logger;
import spark.Request;
import spark.Response;

@GlobalControllerManifest
public class XPathController implements RestController {

    private final Gson gson;
    private final Logger logger;

    public XPathController(Gson gson, Logger logger) {
        this.gson = gson;
        this.logger = logger;
    }

    @ScopedControllerManifest(method = HandlerType.POST, path = "/xpath")
    public void transform(Request request, Response response) {
        String body = request.body();

        JsonObject requestJson;
        try {
            requestJson = this.gson.fromJson(body, JsonObject.class);
        } catch (Exception e) {
            JsonObject responseJson = new JsonObject();
            responseJson.addProperty("result", e.getMessage());
            responseJson.addProperty("processor", "N/A");
            responseJson.addProperty("status", "ERR");
            responseJson.addProperty("time", "N/A");

            response.status(400);
            response.body(this.gson.toJson(responseJson));
            return;
        }

        String data = requestJson.get("data").getAsString();
        String query = requestJson.get("process").getAsString();
        String processor = requestJson.get("processor").getAsString();
        String version = requestJson.get("version").getAsString();

        String tmp = "";
        long timeStart;
        long duration;

        if (processor == null) {
            response.body("saxon, xalan");
            return;
        }

        JsonObject responseJson = new JsonObject();
        switch (processor) {
            case "saxon":
                response.header("processor", "Saxon " + Saxon.getVersion() + " " + version + " over s9api");
                timeStart = System.currentTimeMillis();

                try {
                    tmp = Saxon.processXPath(data, query, version).getData().trim();

                    response.status(200);

                    responseJson.addProperty("result", tmp);
                    responseJson.addProperty("status", "OK");
                } catch (Exception ex) {
                    this.logger.error("Error on processing XPath using Saxon. " + ex);

                    response.status(400);

                    responseJson.addProperty("result", ex.getMessage());
                    responseJson.addProperty("status", "ERR");
                }

                duration = System.currentTimeMillis() - timeStart;
                this.logger.info("Request (XPath, Saxon) processed in " + duration + " ms.");

                responseJson.addProperty("processor", "Saxon " + Saxon.getVersion() + " " + version + " over s9api");
                responseJson.addProperty("time", duration);

                response.body(this.gson.toJson(responseJson));
                return;

            case "xalan":
                response.header("processor", Xalan.getVersion());
                timeStart = System.currentTimeMillis();

                try {
                    XPathQueryResult xPathQueryResult = Xalan.processXPath(data, query);

                    response.status(200);

                    responseJson.addProperty("result", xPathQueryResult.getData().trim());
                    responseJson.addProperty("status", "OK");
                    responseJson.addProperty("type", xPathQueryResult.getType());
                } catch (Exception ex) {
                    this.logger.error("Error on processing XPath using Xalan. " + ex);

                    response.status(400);

                    responseJson.addProperty("result", ex.getMessage());
                    responseJson.addProperty("status", "ERR");
                }

                duration = System.currentTimeMillis() - timeStart;
                this.logger.info("Request (XPath, Xalan) processed in " + duration + " ms.");

                responseJson.addProperty("processor", Xalan.getVersion());
                responseJson.addProperty("time", duration);

                response.body(this.gson.toJson(responseJson));
                return;
            default:
                response.body("saxon, xalan");
        }
    }
}
