/*
 * Copyright (c) 2019, 2022 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.glassfish.jersey.wadl.doclet;

import com.sun.source.doctree.DocCommentTree;
import com.sun.source.doctree.DocTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.util.DocTrees;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.util.ElementFilter;
import javax.tools.Diagnostic.Kind;
import javax.xml.namespace.QName;

import org.glassfish.jersey.server.wadl.internal.generators.resourcedoc.model.AnnotationDocType;
import org.glassfish.jersey.server.wadl.internal.generators.resourcedoc.model.ClassDocType;
import org.glassfish.jersey.server.wadl.internal.generators.resourcedoc.model.MethodDocType;
import org.glassfish.jersey.server.wadl.internal.generators.resourcedoc.model.NamedValueType;
import org.glassfish.jersey.server.wadl.internal.generators.resourcedoc.model.ParamDocType;
import org.glassfish.jersey.server.wadl.internal.generators.resourcedoc.model.RepresentationDocType;
import org.glassfish.jersey.server.wadl.internal.generators.resourcedoc.model.RequestDocType;
import org.glassfish.jersey.server.wadl.internal.generators.resourcedoc.model.ResourceDocType;
import org.glassfish.jersey.server.wadl.internal.generators.resourcedoc.model.ResponseDocType;
import org.glassfish.jersey.server.wadl.internal.generators.resourcedoc.model.WadlParamType;

import jdk.javadoc.doclet.Doclet;
import jdk.javadoc.doclet.DocletEnvironment;
import jdk.javadoc.doclet.Reporter;

/**
 * Creates a resourcedoc XML file.
 * <p/>
 * <p>
 * The ResourceDoc file contains the javadoc documentation of resource classes,
 * so that this can be used for extending generated wadl with useful
 * documentation.
 * </p>
 *
 * @author <a href="mailto:jorge.bescos.gascon@oracle.com">Jorge Bescos
 *         Gascon</a>
 */
public class ResourceDoclet implements Doclet {

    private static final Logger LOG = Logger.getLogger(ResourceDoclet.class.getName());
    private static final Pattern PATTERN_RESPONSE_REPRESENTATION = Pattern.compile("@response\\.representation\\.([\\d]+)\\..*");
    private static final Pattern PATTERN_INLINE_TAG = Pattern
            .compile("(?!\\{)[\\w\\?\\!\\#\\<\\>\\.\\ \\/\\:\\\\-\\{\\}]+(?=\\})");
    private static final String COMA = ", ";
    private static final String EMPTY = "";
    private static final String SPACE = " ";
    private final OptionOutput optionOutput = new OptionOutput();
    private final OptionClasspath optionClasspath = new OptionClasspath();
    private final OptionDocprocessor optionDocprocessor = new OptionDocprocessor();

    @Override
    public void init(Locale locale, Reporter reporter) {
        reporter.print(Kind.NOTE, "Doclet using locale: " + locale);
    }

    private String getComments(DocCommentTree docCommentTree) {
        if (docCommentTree != null) {
            StringBuilder body = new StringBuilder();
            docCommentTree.getFullBody().forEach(doc -> body.append(doc.toString()));
            return body.toString();
        } else {
            return EMPTY;
        }
    }

    private Map<DocTree.Kind, Map<String, String>> getTags(DocCommentTree docCommentTree) {
        Map<DocTree.Kind, Map<String, String>> tags = new HashMap<>();
        if (docCommentTree != null) {
            for (DocTree tag : docCommentTree.getBlockTags()) {
                Map<String, String> tagsInKind = tags.get(tag.getKind());
                if (tagsInKind == null) {
                    tagsInKind = new HashMap<>();
                    tags.put(tag.getKind(), tagsInKind);
                }
                String[] kindValuePair = getTagPair(tag.toString());
                if (tag.getKind() == DocTree.Kind.PARAM) {
                    // Adds the parameter name and description
                    String[] paramValuePair = getTagPair(kindValuePair[1]);
                    tagsInKind.put(paramValuePair[0], paramValuePair[1]);
                } else {
                    // Adds the @tag name and description
                    tagsInKind.put(kindValuePair[0], kindValuePair[1]);
                }
            }
        }
        return tags;
    }

    private String[] getTagPair(String tag) {
        String[] pair = tag.split(SPACE, 2);
        if (pair.length != 2) {
            pair = new String[]{pair[0], null};
        }
        return pair;
    }

    @Override
    public boolean run(DocletEnvironment docEnv) {
        boolean success = true;
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        try {
            ClassLoader ncl = new Loader(optionClasspath.getClasspathElements(), ResourceDoclet.class.getClassLoader());
            Thread.currentThread().setContextClassLoader(ncl);
            DocProcessorWrapper docProcessor = new DocProcessorWrapper();
            if (optionDocprocessor.getDocProcessors().length != 0) {
                try {
                    Class<?> clazz = Class.forName(optionDocprocessor.getDocProcessors()[0], true,
                            Thread.currentThread().getContextClassLoader());
                    Class<? extends DocProcessor> dpClazz = clazz.asSubclass(DocProcessor.class);
                    docProcessor.add((DocProcessor) dpClazz.getDeclaredConstructors()[0].newInstance());
                } catch (Exception e) {
                    LOG.log(Level.SEVERE,
                            "Could not load docProcessors " + Arrays.asList(optionDocprocessor.getDocProcessors()), e);
                }
            }
            ResourceDocType result = new ResourceDocType();
            for (TypeElement element : ElementFilter.typesIn(docEnv.getIncludedElements())) {
                DocTrees docTrees = docEnv.getDocTrees();
                DocCommentTree docCommentTree = docTrees.getDocCommentTree(element);
                if (docCommentTree != null) {
                    ClassDocType classDocType = new ClassDocType();
                    classDocType.setClassName(element.getQualifiedName().toString());
                    classDocType.setCommentText(getComments(docCommentTree));
                    docProcessor.processClassDocWithDocEnv(element, classDocType, docEnv);
                    for (ExecutableElement method : ElementFilter.methodsIn(element.getEnclosedElements())) {
                        Map<DocTree.Kind, Map<String, String>> tags = getTags(docTrees.getDocCommentTree(method));
                        MethodTree methodTree = docTrees.getTree(method);
                        MethodDocType methodDocType = new MethodDocType();
                        if (methodTree != null) {
                            methodDocType.setMethodName(methodTree.getName().toString());
                            methodDocType.setCommentText(getComments(docTrees.getDocCommentTree(method)));
                        }
                        getTags(docTrees.getDocCommentTree(method));
                        StringBuilder arguments = new StringBuilder("(");
                        Map<String, String> paramTags = tags.get(DocTree.Kind.PARAM);
                        for (VariableElement parameter : method.getParameters()) {
                            ParamDocType paramDocType = buildParamDocType(parameter, paramTags);
                            arguments.append(parameter.asType()).append(COMA);
                            if (paramDocType != null) {
                                methodDocType.getParamDocs().add(paramDocType);
                                docProcessor.processParamTagWithDocEnv(parameter, paramDocType, docEnv);
                            }
                        }
                        // Remove last comma if there are parameters
                        if (arguments.length() != 1) {
                            arguments.delete(arguments.length() - COMA.length(), arguments.length());
                        }
                        arguments.append(")");
                        methodDocType.setMethodSignature(arguments.toString());
                        docProcessor.processMethodDocWithDocEnv(method, methodDocType, docEnv);
                        methodDocType.setRequestDoc(buildRequestDocType(tags));
                        methodDocType.setResponseDoc(buildResponseDocType(tags));
                        classDocType.getMethodDocs().add(methodDocType);
                    }
                    result.getDocs().add(classDocType);
                    success = DocletUtils.createOutputFile(optionOutput.getValue(), docProcessor, result);
                    
                }
            }
        } finally {
            Thread.currentThread().setContextClassLoader(cl);
        }
        return success;
    }

    private ParamDocType buildParamDocType(VariableElement parameter, Map<String, String> paramTags) {
        if (paramTags != null) {
            ParamDocType paramDocType = new ParamDocType();
            paramDocType.setParamName(parameter.getSimpleName().toString());
            paramDocType.setCommentText(paramTags.get(paramDocType.getParamName()));
            for (AnnotationMirror annotation : parameter.getAnnotationMirrors()) {
                AnnotationDocType annotationDocType = new AnnotationDocType();
                annotationDocType.setAnnotationTypeName(annotation.getAnnotationType().toString());
                for (Entry<? extends ExecutableElement, ? extends AnnotationValue> pair : annotation.getElementValues()
                        .entrySet()) {
                    NamedValueType namedValueType = new NamedValueType();
                    namedValueType.setName(pair.getKey().getSimpleName().toString());
                    namedValueType.setValue(pair.getValue().getValue().toString());
                    annotationDocType.getAttributeDocs().add(namedValueType);
                }
                paramDocType.getAnnotationDocs().add(annotationDocType);
            }
            return paramDocType;
        }
        return null;
    }

    private RequestDocType buildRequestDocType(Map<DocTree.Kind, Map<String, String>> tags) {
        Map<String, String> customTags = tags.get(DocTree.Kind.UNKNOWN_BLOCK_TAG);
        if (customTags != null) {
            RequestDocType requestDoc = new RequestDocType();
            RepresentationDocType representationDoc = new RepresentationDocType();
            String qname = customTags.get("@request.representation.qname");
            String example = customTags.get("@request.representation.example");
            if (qname != null) {
                representationDoc.setElement(QName.valueOf(qname));
            }
            if (example != null) {
                representationDoc.setExample(getSerializedExample(example));
            }
            if (qname != null || example != null) {
                requestDoc.setRepresentationDoc(representationDoc);
                return requestDoc;
            }
        }
        return null;
    }

    private ResponseDocType buildResponseDocType(Map<DocTree.Kind, Map<String, String>> tags) {
        ResponseDocType responseDoc = new ResponseDocType();
        Map<String, String> returnDoc = tags.get(DocTree.Kind.RETURN);
        if (returnDoc != null) {
            responseDoc.setReturnDoc(returnDoc.get("@return"));
        }
        Map<String, String> customTags = tags.get(DocTree.Kind.UNKNOWN_BLOCK_TAG);
        if (customTags != null) {
            String responseParam = customTags.remove("@response.param");
            if (responseParam != null) {
                Matcher matcher = PATTERN_INLINE_TAG.matcher(responseParam);
                WadlParamType wadlParam = new WadlParamType();
                while (matcher.find()) {
                    String group = matcher.group();
                    String[] pair = getTagPair(group);
                    switch (pair[0]) {
                    case "name":
                        wadlParam.setName(pair[1]);
                        break;
                    case "style":
                        wadlParam.setStyle(pair[1]);
                        break;
                    case "type":
                        wadlParam.setType(QName.valueOf(pair[1]));
                        break;
                    case "doc":
                        wadlParam.setDoc(pair[1]);
                        break;
                    default:
                        LOG.warning("Unknown inline tag of @response.param: @" + pair[0] + " (value: " + pair[1] + ")");
                        break;
                    }
                }
                responseDoc.getWadlParams().add(wadlParam);
            }
            Map<Long, RepresentationDocType> groupedRepresentationDocType = new HashMap<>();
            for (Entry<String, String> entry : customTags.entrySet()) {
                if (entry.getKey().startsWith("@response.representation")) {
                    String[] keySplit = entry.getKey().split("\\.");
                    long httpCode = Long.parseLong(keySplit[2]);
                    RepresentationDocType representationDoc = groupedRepresentationDocType.get(httpCode);
                    if (representationDoc == null) {
                        representationDoc = new RepresentationDocType();
                        representationDoc.setStatus(httpCode);
                        groupedRepresentationDocType.put(httpCode, representationDoc);
                    }
                    if ("qname".equals(keySplit[3])) {
                        representationDoc.setElement(QName.valueOf(entry.getValue()));
                    } else if ("mediaType".equals(keySplit[3])) {
                        representationDoc.setMediaType(entry.getValue());
                    } else if ("example".equals(getSerializedExample(keySplit[3]))) {
                        representationDoc.setExample(getSerializedExample(entry.getValue()));
                    } else if ("doc".equals(keySplit[3])) {
                        representationDoc.setDoc(entry.getValue());
                    } else {
                        LOG.warning("Unknown response representation tag " + entry.getKey());
                    }
                }
            }
            responseDoc.getRepresentations().addAll(groupedRepresentationDocType.values());
        }
        return responseDoc;
    }

    @Override
    public String getName() {
        return getClass().getCanonicalName();
    }

    @Override
    public Set<? extends Option> getSupportedOptions() {
        return new HashSet<>(Arrays.asList(optionOutput, optionClasspath, optionDocprocessor));
    }

    @Override
    public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.latest();
    }

    private String getSerializedExample(String tag) {
        if (tag != null) {
            Matcher matcher = PATTERN_INLINE_TAG.matcher(tag);
            while (matcher.find()) {
                String group = matcher.group();
                String[] pair = getTagPair(group);
                if ("link".equals(pair[0])) {
                    String[] classAndField = pair[1].split("#");
                    return DocletUtils.getLinkClass(classAndField[0], classAndField[1]);
                } else {
                    return pair[1];
                }
            }
        }
        return tag;
    }

}
