/*
 * Copyright 2016-present Open Networking Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.onosproject.onosjar;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.io.ByteStreams;
import com.google.common.io.Files;
import com.thoughtworks.qdox.JavaProjectBuilder;
import com.thoughtworks.qdox.model.DocletTag;
import com.thoughtworks.qdox.model.JavaAnnotation;
import com.thoughtworks.qdox.model.JavaClass;
import com.thoughtworks.qdox.model.JavaMethod;
import com.thoughtworks.qdox.model.JavaParameter;
import com.thoughtworks.qdox.model.JavaType;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import static com.google.common.base.Strings.isNullOrEmpty;

/**
 * Generates Swagger JSON artifacts from the Java source files.
 */
public class SwaggerGenerator {

    private final ObjectMapper mapper = new ObjectMapper();

    private static final String JSON_FILE = "swagger.json";
    private static final String GEN_SRC = "generated-sources";
    private static final String REG_SRC = "/registrator.javat";

    private static final String PATH = "javax.ws.rs.Path";
    private static final String PATH_PARAM = "javax.ws.rs.PathParam";
    private static final String QUERY_PARAM = "javax.ws.rs.QueryParam";
    private static final String POST = "javax.ws.rs.POST";
    private static final String PATCH = "javax.ws.rs.PATCH";
    private static final String GET = "javax.ws.rs.GET";
    private static final String PUT = "javax.ws.rs.PUT";
    private static final String DELETE = "javax.ws.rs.DELETE";
    private static final String PRODUCES = "javax.ws.rs.Produces";
    private static final String CONSUMES = "javax.ws.rs.Consumes";
    private static final String JSON = "MediaType.APPLICATION_JSON";
    private static final String OCTET_STREAM = "MediaType.APPLICATION_OCTET_STREAM";
    private static final String RESPONSES = "io.swagger.annotations.ApiResponses";

    private final List<File> srcs;
    private final List<File> resources;
    private final File srcDirectory;
    private final File resourceDirectory;
    private final File genSrcOutputDirectory;
    private final File genResourcesOutputDirectory;
    private final String webContext;
    private final String apiTitle;
    private final String apiVersion;
    private final String apiPackage;
    private final String apiDescription;

    public SwaggerGenerator(List<File> srcs, List<File> resources,
                            File srcDirectory, File resourceDirectory,
                            File genSrcOutputDirectory, File genResourcesOutputDirectory,
                            String webContext, String apiTitle, String apiVersion,
                            String apiPackage, String apiDescription) {
        this.srcs = srcs;
        this.resources = resources;
        this.srcDirectory = srcDirectory;
        this.resourceDirectory = resourceDirectory;
        this.genSrcOutputDirectory = genSrcOutputDirectory;
        this.genResourcesOutputDirectory = genResourcesOutputDirectory;
        this.webContext = webContext;

        this.apiTitle = apiTitle;
        this.apiVersion = apiVersion;
        this.apiPackage = apiPackage;
        this.apiDescription = apiDescription;
    }

    public void execute() {
        try {
            JavaProjectBuilder builder = new JavaProjectBuilder();
            if (srcDirectory != null) {
                builder.addSourceTree(new File(srcDirectory, "src/main/java"));
            }
            if (srcs != null) {
                srcs.forEach(src -> {
                    if (src.toString().endsWith(".java")) {
                        try {
                            builder.addSource(src);
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                    }
                });
            }

            ObjectNode root = initializeRoot(webContext, apiTitle, apiVersion, apiDescription);
            ArrayNode tags = mapper.createArrayNode();
            ObjectNode paths = mapper.createObjectNode();
            ObjectNode definitions = mapper.createObjectNode();

            root.set("tags", tags);
            root.set("paths", paths);
            root.set("definitions", definitions);

            // TODO: Process resources to allow lookup of files by name

            builder.getClasses().forEach(jc -> processClass(jc, paths, tags, definitions, srcDirectory));

            if (paths.size() > 0) {
                genCatalog(genResourcesOutputDirectory, root);
                if (!isNullOrEmpty(apiPackage)) {
                    genRegistrator(genSrcOutputDirectory, webContext, apiTitle, apiVersion,
                                   apiPackage, apiDescription);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("Unable to generate ONOS REST API documentation", e);
        }
    }

    // initializes top level root with Swagger required specifications
    private ObjectNode initializeRoot(String webContext, String apiTitle,
                                      String apiVersion, String apiDescription) {
        ObjectNode root = mapper.createObjectNode();
        root.put("swagger", "2.0");
        ObjectNode info = mapper.createObjectNode();
        root.set("info", info);

        root.put("basePath", webContext);
        info.put("version", apiVersion);
        info.put("title", apiTitle);
        info.put("description", apiDescription);

        ArrayNode produces = mapper.createArrayNode();
        produces.add("application/json");
        root.set("produces", produces);

        ArrayNode consumes = mapper.createArrayNode();
        consumes.add("application/json");
        root.set("consumes", consumes);

        return root;
    }

    // Checks whether javaClass has a path tag associated with it and if it does
    // processes its methods and creates a tag for the class on the root
    void processClass(JavaClass javaClass, ObjectNode paths, ArrayNode tags,
                      ObjectNode definitions, File srcDirectory) {
        // If the class does not have a Path tag then ignore it
        JavaAnnotation annotation = getPathAnnotation(javaClass);
        if (annotation == null) {
            return;
        }

        String path = getPath(annotation);
        if (path == null) {
            return;
        }

        String resourcePath = "/" + path;
        String tagPath = path.isEmpty() ? "/" : path;

        // Create tag node for this class.
        ObjectNode tagObject = mapper.createObjectNode();
        tagObject.put("name", tagPath);
        if (javaClass.getComment() != null) {
            tagObject.put("description", shortText(javaClass.getComment()));
        }
        tags.add(tagObject);

        // Create an array node add to all methods from this class.
        ArrayNode tagArray = mapper.createArrayNode();
        tagArray.add(tagPath);

        processAllMethods(javaClass, resourcePath, paths, tagArray, definitions, srcDirectory);
    }

    private JavaAnnotation getPathAnnotation(JavaClass javaClass) {
        Optional<JavaAnnotation> optional = javaClass.getAnnotations()
                .stream().filter(a -> a.getType().getName().equals(PATH)).findAny();
        return optional.orElse(null);
    }

    // Checks whether a class's methods are REST methods and then places all the
    // methods under a specific path into the paths node
    private void processAllMethods(JavaClass javaClass, String resourcePath,
                                   ObjectNode paths, ArrayNode tagArray, ObjectNode definitions,
                                   File srcDirectory) {
        // map of the path to its methods represented by an ObjectNode
        Map<String, ObjectNode> pathMap = new HashMap<>();

        javaClass.getMethods().forEach(javaMethod -> {
            javaMethod.getAnnotations().forEach(annotation -> {
                String name = annotation.getType().getName();
                if (name.equals(PATCH) || name.equals(POST) || name.equals(GET) || name.equals(DELETE) ||
                        name.equals(PUT)) {
                    // substring(12) removes "javax.ws.rs."
                    String method = annotation.getType().toString().substring(12).toLowerCase();
                    processRestMethod(javaMethod, method, pathMap, resourcePath, tagArray, definitions, srcDirectory);
                }
            });
        });

        // for each path add its methods to the path node
        for (Map.Entry<String, ObjectNode> entry : pathMap.entrySet()) {
            paths.set(entry.getKey(), entry.getValue());
        }


    }

    private void processRestMethod(JavaMethod javaMethod, String method,
                                   Map<String, ObjectNode> pathMap,
                                   String resourcePath, ArrayNode tagArray,
                                   ObjectNode definitions, File srcDirectory) {
        String fullPath = resourcePath, consumes = "", produces = "",
                comment = javaMethod.getComment();
        DocletTag tag = javaMethod.getTagByName("onos.rsModel");
        for (JavaAnnotation annotation : javaMethod.getAnnotations()) {
            String name = annotation.getType().getName();
            if (name.equals(PATH)) {
                fullPath = resourcePath + "/" + getPath(annotation);
                fullPath = fullPath.replaceFirst("^//", "/");
            }
            if (name.equals(CONSUMES)) {
                consumes = getIOType(annotation);
            }
            if (name.equals(PRODUCES)) {
                produces = getIOType(annotation);
            }
        }
        ObjectNode methodNode = mapper.createObjectNode();
        methodNode.set("tags", tagArray);

        addSummaryDescriptions(methodNode, comment);
        addJsonSchemaDefinition(srcDirectory, definitions, tag);

        processParameters(javaMethod, methodNode, method, tag);

        processConsumesProduces(methodNode, "consumes", consumes);
        processConsumesProduces(methodNode, "produces", produces);
        if (tag == null || !(tag.getParameters().size() > 1)) {
            addResponses(javaMethod, methodNode, tag, false);
        } else {
            addResponses(javaMethod, methodNode, tag, true);
        }

        ObjectNode operations = pathMap.get(fullPath);
        if (operations == null) {
            operations = mapper.createObjectNode();
            operations.set(method, methodNode);
            pathMap.put(fullPath, operations);
        } else {
            operations.set(method, methodNode);
        }
    }

    private void addJsonSchemaDefinition(File srcDirectory, ObjectNode definitions, DocletTag tag) {
        final File definitionsDirectory;
        if (resourceDirectory != null) {
            definitionsDirectory = new File(resourceDirectory, "definitions");
        } else if (srcDirectory != null) {
            definitionsDirectory = new File(srcDirectory + "/src/main/resources/definitions");
        } else {
            definitionsDirectory = null;
        }
        if (tag != null) {
            tag.getParameters().forEach(param -> {
                try {
                    File config;
                    if (definitionsDirectory != null) {
                        config = new File(definitionsDirectory.getAbsolutePath() + "/" + param + ".json");
                    } else {
                        config = resources.stream().filter(f -> f.getName().equals(param + ".json")).findFirst().orElse(null);
                    }
                    definitions.set(param, mapper.readTree(config));
                } catch (IOException e) {
                    throw new RuntimeException(String.format("Could not process %s in %s@%s: %s",
                                                             tag.getName(), tag.getContext(), tag.getLineNumber(),
                                                             e.getMessage()), e);
                }
            });
        }
    }

    private void processConsumesProduces(ObjectNode methodNode, String type, String io) {
        if (!io.equals("")) {
            ArrayNode array = mapper.createArrayNode();
            methodNode.set(type, array);
            array.add(io);
        }
    }

    private void addSummaryDescriptions(ObjectNode methodNode, String comment) {
        String summary = "", description;
        if (comment != null) {
            if (comment.contains(".")) {
                int periodIndex = comment.indexOf(".");
                summary = comment.substring(0, periodIndex);
                description = comment.length() > periodIndex + 1 ?
                        comment.substring(periodIndex + 1).trim() : "";
            } else {
                description = comment;
            }
            methodNode.put("summary", summary);
            methodNode.put("description", description);
        }
    }

    private Optional<JavaAnnotation> getResponsesAnnotation(JavaMethod javaMethod) {
        return javaMethod.getAnnotations().stream().filter(
                a -> a.getType().getName().equals(RESPONSES)
        ).findAny();
    }

    // TODO: add json schema for responses
    private void addResponses(JavaMethod javaMethod, ObjectNode methodNode, DocletTag tag, boolean responseJson) {
        ObjectNode responses = mapper.createObjectNode();
        methodNode.set("responses", responses);

        Optional<JavaAnnotation> responsesAnnotation = getResponsesAnnotation(javaMethod);

        if (responsesAnnotation.isPresent()) {
            Object annotationsObj = responsesAnnotation.get().getNamedParameter("value");
            if (annotationsObj != null && annotationsObj instanceof List) {
                List<JavaAnnotation> responseAnnotation = (List<JavaAnnotation>) annotationsObj;
                responseAnnotation.forEach(
                        javaAnnotation -> {
                            ObjectNode response = mapper.createObjectNode();
                            response.put("description",
                                    String.valueOf(javaAnnotation.getNamedParameter("message"))
                                            .replaceAll("^\"|\"$", ""));
                            responses.set(String.valueOf(javaAnnotation.getNamedParameter("code")), response);
                        }
                );
            }
        } else {
            ObjectNode success = mapper.createObjectNode();
            success.put("description", "successful operation");
            responses.set("200", success);

            ObjectNode defaultObj = mapper.createObjectNode();
            defaultObj.put("description", "Unexpected error");
            responses.set("default", defaultObj);

            if (tag != null && responseJson) {
                ObjectNode schema = mapper.createObjectNode();
                tag.getParameters().stream().forEach(
                        param -> schema.put("$ref", "#/definitions/" + param));
                success.set("schema", schema);
            }
        }
    }

    // Checks if the annotations has a value of JSON and returns the string
    // that Swagger requires
    private String getIOType(JavaAnnotation annotation) {
        if (annotation.getNamedParameter("value").toString().equals(JSON)) {
            return "application/json";
        } else if (annotation.getNamedParameter("value").toString().equals(OCTET_STREAM)) {
            return "application/octet_stream";
        }
        return "";
    }

    // If the annotation has a Path tag, returns the value with leading and
    // trailing double quotes and slash removed.
    private String getPath(JavaAnnotation annotation) {
        String path = annotation.getNamedParameter("value").toString();
        return path == null ? null : path.replaceAll("(^[\\\"/]*|[/\\\"]*$)", "");
    }

    // Processes parameters of javaMethod and enters the proper key-values into the methodNode
    private void processParameters(JavaMethod javaMethod, ObjectNode methodNode, String method, DocletTag tag) {
        ArrayNode parameters = mapper.createArrayNode();
        methodNode.set("parameters", parameters);
        boolean required = true;

        for (JavaParameter javaParameter : javaMethod.getParameters()) {
            ObjectNode individualParameterNode = mapper.createObjectNode();
            Optional<JavaAnnotation> optional = javaParameter.getAnnotations().stream().filter(
                    annotation -> annotation.getType().getName().equals(PATH_PARAM) ||
                            annotation.getType().getName().equals(QUERY_PARAM)).findAny();
            JavaAnnotation pathType = optional.orElse(null);

            String annotationName = javaParameter.getName();


            if (pathType != null) { //the parameter is a path or query parameter
                individualParameterNode.put("name",
                                            pathType.getNamedParameter("value")
                                                    .toString().replace("\"", ""));
                if (pathType.getType().getName().equals(PATH_PARAM)) {
                    individualParameterNode.put("in", "path");
                } else if (pathType.getType().getName().equals(QUERY_PARAM)) {
                    individualParameterNode.put("in", "query");
                }
                individualParameterNode.put("type", getType(javaParameter.getType()));
            } else { // the parameter is a body parameter
                individualParameterNode.put("name", annotationName);
                individualParameterNode.put("in", "body");

                // Adds the reference to the Json model for the input
                // that goes in the post or put operation
                if (tag != null && (method.toLowerCase().equals("post") ||
                        method.toLowerCase().equals("put"))) {
                    ObjectNode schema = mapper.createObjectNode();
                    tag.getParameters().stream().forEach(param -> {
                        schema.put("$ref", "#/definitions/" + param);
                    });
                    individualParameterNode.set("schema", schema);
                }
            }
            for (DocletTag p : javaMethod.getTagsByName("param")) {
                if (p.getValue().contains(annotationName)) {
                    String description = "";
                    if (p.getValue().split(" ", 2).length >= 2) {
                        description = p.getValue().split(" ", 2)[1].trim();
                        if (description.contains("optional")) {
                            required = false;
                        }
                    } else {
                        throw new RuntimeException(String.format("No description for parameter \"%s\" in " +
                                                                         "method \"%s\" in %s (line %d)",
                                                                 p.getValue(), javaMethod.getName(),
                                                                 javaMethod.getDeclaringClass().getName(),
                                                                 javaMethod.getLineNumber()));
                    }
                    individualParameterNode.put("description", description);
                }
            }
            individualParameterNode.put("required", required);
            parameters.add(individualParameterNode);
        }
    }

    // Returns the Swagger specified strings for the type of a parameter
    private String getType(JavaType javaType) {
        String type = javaType.getFullyQualifiedName();
        String value;
        if (type.equals(String.class.getName())) {
            value = "string";
        } else if (type.equals("int")) {
            value = "integer";
        } else if (type.equals(boolean.class.getName())) {
            value = "boolean";
        } else if (type.equals(long.class.getName())) {
            value = "number";
        } else {
            value = "";
        }
        return value;
    }

    // Writes the swagger.json file using the supplied JSON root.
    private void genCatalog(File dstDirectory, ObjectNode root) {
        File swaggerCfg = new File(dstDirectory, JSON_FILE);
        if (dstDirectory.exists() || dstDirectory.mkdirs()) {
            try (FileWriter fw = new FileWriter(swaggerCfg);
                 PrintWriter pw = new PrintWriter(fw)) {
                pw.println(root.toString());
            } catch (IOException e) {
                throw new RuntimeException("Unable to write " + JSON_FILE, e);
            }
        } else {
            throw new RuntimeException("Unable to create " + dstDirectory);
        }
    }

    // Generates the registrator Java component.
    private void genRegistrator(File dstDirectory, String webContext,
                                String apiTitle, String apiVersion,
                                String apiPackage, String apiDescription) {
        File dir = new File(dstDirectory, resourceDirectory != null ? GEN_SRC : ".");
        File reg = new File(dir, apiRegistratorPath(apiPackage));
        File pkg = reg.getParentFile();
        if (pkg.exists() || pkg.mkdirs()) {
            try {
                String src = new String(ByteStreams.toByteArray(getClass().getResourceAsStream(REG_SRC)));
                src = src.replace("${api.package}", apiPackage)
                        .replace("${web.context}", webContext)
                        .replace("${api.title}", apiTitle)
                        .replace("${api.description}", apiDescription);
                Files.write(src.getBytes(), reg);
            } catch (IOException e) {
                throw new RuntimeException("Unable to write " + reg, e);
            }
        } else {
            throw new RuntimeException("Unable to create " + reg);
        }
    }

    private String shortText(String comment) {
        int i = comment.indexOf('.');
        return i > 0 ? comment.substring(0, i) : comment;
    }

    public static String apiRegistratorPath(String apiPackage) {
        return apiPackage.replaceAll("\\.", "/") + "/ApiDocRegistrator.java";
    }
}