/*
 * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package jdk.javadoc.internal.doclets.formats.html;

import java.util.List;
import javax.lang.model.element.Element;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.SimpleElementVisitor9;

import com.sun.source.doctree.DocTree;
import com.sun.source.doctree.IndexTree;
import com.sun.tools.javac.util.DefinedBy;

import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
import jdk.javadoc.internal.doclets.toolkit.Configuration;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.builders.SerializedFormBuilder;
import jdk.javadoc.internal.doclets.toolkit.taglets.TagletWriter;
import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
import jdk.javadoc.internal.doclets.toolkit.util.DocLink;
import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
import jdk.javadoc.internal.doclets.toolkit.util.MessageRetriever;
import jdk.javadoc.internal.doclets.toolkit.util.Utils;

/**
 * The taglet writer that writes HTML.
 *
 *  <p><b>This is NOT part of any supported API.
 *  If you write code that depends on this, you do so at your own risk.
 *  This code and its internal interfaces are subject to change or
 *  deletion without notice.</b>
 *
 * @author Jamie Ho
 * @author Bhavesh Patel (Modified)
 */

public class TagletWriterImpl extends TagletWriter {

    private final HtmlDocletWriter htmlWriter;
    private final ConfigurationImpl configuration;
    private final Utils utils;

    public TagletWriterImpl(HtmlDocletWriter htmlWriter, boolean isFirstSentence) {
        super(isFirstSentence);
        this.htmlWriter = htmlWriter;
        configuration = htmlWriter.configuration;
        this.utils = configuration.utils;
    }

    /**
     * {@inheritDoc}
     */
    public Content getOutputInstance() {
        return new ContentBuilder();
    }

    /**
     * {@inheritDoc}
     */
    protected Content codeTagOutput(Element element, DocTree tag) {
        CommentHelper ch = utils.getCommentHelper(element);
        String str = utils.normalizeNewlines(ch.getText(tag));
        StringContent content = new StringContent(str);
        Content result = HtmlTree.CODE(content);
        return result;
    }

    protected Content indexTagOutput(Element element, DocTree tag) {
        CommentHelper ch = utils.getCommentHelper(element);
        IndexTree itt = (IndexTree)tag;

        String tagText =  ch.getText(itt.getSearchTerm());
        if (tagText.charAt(0) == '"' && tagText.charAt(tagText.length() - 1) == '"') {
            tagText = tagText.substring(1, tagText.length() - 1);
        }
        String desc = ch.getText(itt.getDescription());

        String anchorName = htmlWriter.getName(tagText);
        Content result = HtmlTree.A_ID(anchorName, new StringContent(tagText));
        if (configuration.createindex && !tagText.isEmpty()) {
            SearchIndexItem si = new SearchIndexItem();
            si.setLabel(tagText);
            si.setDescription(desc);
            new SimpleElementVisitor9<Void, Void>() {
                @Override @DefinedBy(DefinedBy.Api.LANGUAGE_MODEL)
                public Void visitPackage(PackageElement e, Void p) {
                    si.setUrl(DocPath.forPackage(e).getPath()
                            + "/" + DocPaths.PACKAGE_SUMMARY.getPath() + "#" + anchorName);
                    si.setHolder(utils.getSimpleName(element));
                    return null;
                }

                @Override @DefinedBy(DefinedBy.Api.LANGUAGE_MODEL)
                public Void visitType(TypeElement e, Void p) {
                    si.setUrl(DocPath.forClass(utils, e).getPath() + "#" + anchorName);
                    si.setHolder(utils.getFullyQualifiedName(e));
                    return null;
                }

                @Override @DefinedBy(DefinedBy.Api.LANGUAGE_MODEL)
                public Void visitVariable(VariableElement e, Void p) {
                    TypeElement te = utils.getEnclosingTypeElement(e);
                    si.setUrl(DocPath.forClass(utils, te).getPath() + "#" + anchorName);
                    si.setHolder(utils.getFullyQualifiedName(e) + "." + utils.getSimpleName(e));
                    return null;
                }

                @Override @DefinedBy(DefinedBy.Api.LANGUAGE_MODEL)
                protected Void defaultAction(Element e, Void p) {
                    TypeElement te = utils.getEnclosingTypeElement(e);
                    si.setUrl(DocPath.forClass(utils, te).getPath() + "#" + anchorName);
                    si.setHolder(utils.getFullyQualifiedName(e));
                    return null;
                }
            }.visit(element);
            si.setCategory(configuration.getResource("doclet.SearchTags").toString());
            configuration.tagSearchIndex.add(si);
        }
        return result;
    }

    /**
     * {@inheritDoc}
     */
    public Content getDocRootOutput() {
        String path;
        if (htmlWriter.pathToRoot.isEmpty())
            path = ".";
        else
            path = htmlWriter.pathToRoot.getPath();
        return new StringContent(path);
    }

    /**
     * {@inheritDoc}
     */
    public Content deprecatedTagOutput(Element element) {
        ContentBuilder result = new ContentBuilder();
        CommentHelper ch = utils.getCommentHelper(element);
        List<? extends DocTree> deprs = utils.getBlockTags(element, DocTree.Kind.DEPRECATED);
        if (utils.isTypeElement(element)) {
            if (utils.isDeprecated(element)) {
                result.addContent(HtmlTree.SPAN(HtmlStyle.deprecatedLabel,
                        new StringContent(configuration.getText("doclet.Deprecated"))));
                result.addContent(RawHtml.nbsp);
                if (!deprs.isEmpty()) {
                    List<? extends DocTree> commentTags = ch.getDescription(configuration, deprs.get(0));
                    if (!commentTags.isEmpty()) {
                        result.addContent(commentTagsToOutput(null, element, commentTags, false));
                    }
                }
            }
        } else {
            if (utils.isDeprecated(element)) {
                result.addContent(HtmlTree.SPAN(HtmlStyle.deprecatedLabel,
                        new StringContent(configuration.getText("doclet.Deprecated"))));
                result.addContent(RawHtml.nbsp);
                if (!deprs.isEmpty()) {
                    List<? extends DocTree> bodyTags = ch.getBody(configuration, deprs.get(0));
                    Content body = commentTagsToOutput(null, element, bodyTags, false);
                    if (!body.isEmpty())
                        result.addContent(HtmlTree.SPAN(HtmlStyle.deprecationComment, body));
                }
            } else {
                if (utils.isDeprecated(utils.getEnclosingTypeElement(element))) {
                    result.addContent(HtmlTree.SPAN(HtmlStyle.deprecatedLabel,
                            new StringContent(configuration.getText("doclet.Deprecated"))));
                    result.addContent(RawHtml.nbsp);
                }
            }
        }
        return result;
    }

    /**
     * {@inheritDoc}
     */
    protected Content literalTagOutput(Element element, DocTree tag) {
        CommentHelper ch = utils.getCommentHelper(element);
        Content result = new StringContent(utils.normalizeNewlines(ch.getText(tag)));
        return result;
    }

    /**
     * {@inheritDoc}
     */
    public MessageRetriever getMsgRetriever() {
        return configuration.message;
    }

    /**
     * {@inheritDoc}
     */
    public Content getParamHeader(String header) {
        HtmlTree result = HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.paramLabel,
                new StringContent(header)));
        return result;
    }

    /**
     * {@inheritDoc}
     */
    public Content paramTagOutput(Element element, DocTree paramTag, String paramName) {
        ContentBuilder body = new ContentBuilder();
        CommentHelper ch = utils.getCommentHelper(element);
        body.addContent(HtmlTree.CODE(new RawHtml(paramName)));
        body.addContent(" - ");
        List<? extends DocTree> description = ch.getDescription(configuration, paramTag);
        body.addContent(htmlWriter.commentTagsToContent(paramTag, element, description, false));
        HtmlTree result = HtmlTree.DD(body);
        return result;
    }

    /**
     * {@inheritDoc}
     */
    public Content propertyTagOutput(Element element, DocTree tag, String prefix) {
        Content body = new ContentBuilder();
        CommentHelper ch = utils.getCommentHelper(element);
        body.addContent(new RawHtml(prefix));
        body.addContent(" ");
        body.addContent(HtmlTree.CODE(new RawHtml(ch.getText(tag))));
        body.addContent(".");
        Content result = HtmlTree.P(body);
        return result;
    }

    /**
     * {@inheritDoc}
     */
    public Content returnTagOutput(Element element, DocTree returnTag) {
        ContentBuilder result = new ContentBuilder();
        CommentHelper ch = utils.getCommentHelper(element);
        result.addContent(HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.returnLabel,
                new StringContent(configuration.getText("doclet.Returns")))));
        result.addContent(HtmlTree.DD(htmlWriter.commentTagsToContent(
                returnTag, element, ch.getDescription(configuration, returnTag), false)));
        return result;
    }

    /**
     * {@inheritDoc}
     */
    public Content seeTagOutput(Element holder, List<? extends DocTree> seeTags) {
        ContentBuilder body = new ContentBuilder();
        if (!seeTags.isEmpty()) {
            for (DocTree dt : seeTags) {
                appendSeparatorIfNotEmpty(body);
                body.addContent(htmlWriter.seeTagToContent(holder, dt));
            }
        }
        if (utils.isVariableElement(holder) && ((VariableElement)holder).getConstantValue() != null &&
                htmlWriter instanceof ClassWriterImpl) {
            //Automatically add link to constant values page for constant fields.
            appendSeparatorIfNotEmpty(body);
            DocPath constantsPath =
                    htmlWriter.pathToRoot.resolve(DocPaths.CONSTANT_VALUES);
            String whichConstant =
                    ((ClassWriterImpl) htmlWriter).getTypeElement().getQualifiedName() + "." +
                    utils.getSimpleName(holder);
            DocLink link = constantsPath.fragment(whichConstant);
            body.addContent(htmlWriter.getHyperLink(link,
                    new StringContent(configuration.getText("doclet.Constants_Summary"))));
        }
        if (utils.isClass(holder) && utils.isSerializable((TypeElement)holder)) {
            //Automatically add link to serialized form page for serializable classes.
            if (SerializedFormBuilder.serialInclude(utils, holder) &&
                      SerializedFormBuilder.serialInclude(utils, utils.containingPackage(holder))) {
                appendSeparatorIfNotEmpty(body);
                DocPath serialPath = htmlWriter.pathToRoot.resolve(DocPaths.SERIALIZED_FORM);
                DocLink link = serialPath.fragment(utils.getFullyQualifiedName(holder));
                body.addContent(htmlWriter.getHyperLink(link,
                        new StringContent(configuration.getText("doclet.Serialized_Form"))));
            }
        }
        if (body.isEmpty())
            return body;

        ContentBuilder result = new ContentBuilder();
        result.addContent(HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.seeLabel,
                new StringContent(configuration.getText("doclet.See_Also")))));
        result.addContent(HtmlTree.DD(body));
        return result;

    }

    private void appendSeparatorIfNotEmpty(ContentBuilder body) {
        if (!body.isEmpty()) {
            body.addContent(", ");
            body.addContent(DocletConstants.NL);
        }
    }

    /**
     * {@inheritDoc}
     */
    public Content simpleTagOutput(Element element, List<? extends DocTree> simpleTags, String header) {
        CommentHelper ch = utils.getCommentHelper(element);
        ContentBuilder result = new ContentBuilder();
        result.addContent(HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.simpleTagLabel, new RawHtml(header))));
        ContentBuilder body = new ContentBuilder();
        boolean many = false;
        for (DocTree simpleTag : simpleTags) {
            if (many) {
                body.addContent(", ");
            }
            List<? extends DocTree> bodyTags = ch.getBody(configuration, simpleTag);
            body.addContent(htmlWriter.commentTagsToContent(simpleTag, element, bodyTags, false));
            many = true;
        }
        result.addContent(HtmlTree.DD(body));
        return result;
    }

    /**
     * {@inheritDoc}
     */
    public Content simpleTagOutput(Element element, DocTree simpleTag, String header) {
        ContentBuilder result = new ContentBuilder();
        result.addContent(HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.simpleTagLabel, new RawHtml(header))));
        CommentHelper ch = utils.getCommentHelper(element);
        List<? extends DocTree> description = ch.getDescription(configuration, simpleTag);
        Content body = htmlWriter.commentTagsToContent(simpleTag, element, description, false);
        result.addContent(HtmlTree.DD(body));
        return result;
    }

    /**
     * {@inheritDoc}
     */
    public Content getThrowsHeader() {
        HtmlTree result = HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.throwsLabel,
                new StringContent(configuration.getText("doclet.Throws"))));
        return result;
    }

    /**
     * {@inheritDoc}
     */
    public Content throwsTagOutput(Element element, DocTree throwsTag) {
        ContentBuilder body = new ContentBuilder();
        CommentHelper ch = utils.getCommentHelper(element);
        Element exception = ch.getException(configuration, throwsTag);
        Content excName;
        if (exception == null) {
            excName = new RawHtml(ch.getExceptionName(throwsTag).toString());
        } else if (exception.asType() == null) {
            excName = new RawHtml(utils.getFullyQualifiedName(exception));
        } else {
            LinkInfoImpl link = new LinkInfoImpl(configuration, LinkInfoImpl.Kind.MEMBER,
                                                 exception.asType());
            link.excludeTypeBounds = true;
            excName = htmlWriter.getLink(link);
        }
        body.addContent(HtmlTree.CODE(excName));
        List<? extends DocTree> description = ch.getDescription(configuration, throwsTag);
        Content desc = htmlWriter.commentTagsToContent(throwsTag, element, description, false);
        if (desc != null && !desc.isEmpty()) {
            body.addContent(" - ");
            body.addContent(desc);
        }
        HtmlTree result = HtmlTree.DD(body);
        return result;
    }

    /**
     * {@inheritDoc}
     */
    public Content throwsTagOutput(TypeMirror throwsType) {
        HtmlTree result = HtmlTree.DD(HtmlTree.CODE(htmlWriter.getLink(
                new LinkInfoImpl(configuration, LinkInfoImpl.Kind.MEMBER, throwsType))));
        return result;
    }

    /**
     * {@inheritDoc}
     */
    public Content valueTagOutput(VariableElement field, String constantVal, boolean includeLink) {
        return includeLink ?
            htmlWriter.getDocLink(LinkInfoImpl.Kind.VALUE_TAG, field,
                constantVal, false) : new RawHtml(constantVal);
    }

    /**
     * {@inheritDoc}
     */
    public Content commentTagsToOutput(DocTree holderTag, List<? extends DocTree> tags) {
        return commentTagsToOutput(holderTag, null, tags, false);
    }

    /**
     * {@inheritDoc}
     */
    public Content commentTagsToOutput(Element holder, List<? extends DocTree> tags) {
        return commentTagsToOutput(null, holder, tags, false);
    }

    /**
     * {@inheritDoc}
     */
    public Content commentTagsToOutput(DocTree holderTag,
        Element holder, List<? extends DocTree> tags, boolean isFirstSentence) {
        return htmlWriter.commentTagsToContent(holderTag, holder,
                tags, isFirstSentence);
    }

    /**
     * {@inheritDoc}
     */
    public Configuration configuration() {
        return configuration;
    }
}
