/*
 * Copyright (c) 1997, 2013, 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 com.sun.tools.javadoc;

import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.sun.javadoc.*;
import com.sun.tools.javac.util.ListBuffer;

/**
 * Comment contains all information in comment part.
 *      It allows users to get first sentence of this comment, get
 *      comment for different tags...
 *
 *  <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 Kaiyang Liu (original)
 * @author Robert Field (rewrite)
 * @author Atul M Dambalkar
 * @author Neal Gafter (rewrite)
 */
class Comment {

    /**
     * sorted comments with different tags.
     */
    private final ListBuffer<Tag> tagList = new ListBuffer<Tag>();

    /**
     * text minus any tags.
     */
    private String text;

    /**
     * Doc environment
     */
    private final DocEnv docenv;

    /**
     * constructor of Comment.
     */
    Comment(final DocImpl holder, final String commentString) {
        this.docenv = holder.env;

        /**
         * Separate the comment into the text part and zero to N tags.
         * Simple state machine is in one of three states:
         * <pre>
         * IN_TEXT: parsing the comment text or tag text.
         * TAG_NAME: parsing the name of a tag.
         * TAG_GAP: skipping through the gap between the tag name and
         * the tag text.
         * </pre>
         */
        @SuppressWarnings("fallthrough")
        class CommentStringParser {
            /**
             * The entry point to the comment string parser
             */
            void parseCommentStateMachine() {
                final int IN_TEXT = 1;
                final int TAG_GAP = 2;
                final int TAG_NAME = 3;
                int state = TAG_GAP;
                boolean newLine = true;
                String tagName = null;
                int tagStart = 0;
                int textStart = 0;
                int lastNonWhite = -1;
                int len = commentString.length();
                for (int inx = 0; inx < len; ++inx) {
                    char ch = commentString.charAt(inx);
                    boolean isWhite = Character.isWhitespace(ch);
                    switch (state)  {
                        case TAG_NAME:
                            if (isWhite) {
                                tagName = commentString.substring(tagStart, inx);
                                state = TAG_GAP;
                            }
                            break;
                        case TAG_GAP:
                            if (isWhite) {
                                break;
                            }
                            textStart = inx;
                            state = IN_TEXT;
                            /* fall thru */
                        case IN_TEXT:
                            if (newLine && ch == '@') {
                                parseCommentComponent(tagName, textStart,
                                                      lastNonWhite+1);
                                tagStart = inx;
                                state = TAG_NAME;
                            }
                            break;
                    }
                    if (ch == '\n') {
                        newLine = true;
                    } else if (!isWhite) {
                        lastNonWhite = inx;
                        newLine = false;
                    }
                }
                // Finish what's currently being processed
                switch (state)  {
                    case TAG_NAME:
                        tagName = commentString.substring(tagStart, len);
                        /* fall thru */
                    case TAG_GAP:
                        textStart = len;
                        /* fall thru */
                    case IN_TEXT:
                        parseCommentComponent(tagName, textStart, lastNonWhite+1);
                        break;
                }
            }

            /**
             * Save away the last parsed item.
             */
            void parseCommentComponent(String tagName,
                                       int from, int upto) {
                String tx = upto <= from ? "" : commentString.substring(from, upto);
                if (tagName == null) {
                    text = tx;
                } else {
                    TagImpl tag;
                    if (tagName.equals("@exception") || tagName.equals("@throws")) {
                        warnIfEmpty(tagName, tx);
                        tag = new ThrowsTagImpl(holder, tagName, tx);
                    } else if (tagName.equals("@param")) {
                        warnIfEmpty(tagName, tx);
                        tag = new ParamTagImpl(holder, tagName, tx);
                    } else if (tagName.equals("@see")) {
                        warnIfEmpty(tagName, tx);
                        tag = new SeeTagImpl(holder, tagName, tx);
                    } else if (tagName.equals("@serialField")) {
                        warnIfEmpty(tagName, tx);
                        tag = new SerialFieldTagImpl(holder, tagName, tx);
                    } else if (tagName.equals("@return")) {
                        warnIfEmpty(tagName, tx);
                        tag = new TagImpl(holder, tagName, tx);
                    } else if (tagName.equals("@author")) {
                        warnIfEmpty(tagName, tx);
                        tag = new TagImpl(holder, tagName, tx);
                    } else if (tagName.equals("@version")) {
                        warnIfEmpty(tagName, tx);
                        tag = new TagImpl(holder, tagName, tx);
                    } else {
                        tag = new TagImpl(holder, tagName, tx);
                    }
                    tagList.append(tag);
                }
            }

            void warnIfEmpty(String tagName, String tx) {
                if (tx.length() == 0) {
                    docenv.warning(holder, "tag.tag_has_no_arguments", tagName);
                }
            }

        }

        new CommentStringParser().parseCommentStateMachine();
    }

    /**
     * Return the text of the comment.
     */
    String commentText() {
        return text;
    }

    /**
     * Return all tags in this comment.
     */
    Tag[] tags() {
        return tagList.toArray(new Tag[tagList.length()]);
    }

    /**
     * Return tags of the specified kind in this comment.
     */
    Tag[] tags(String tagname) {
        ListBuffer<Tag> found = new ListBuffer<Tag>();
        String target = tagname;
        if (target.charAt(0) != '@') {
            target = "@" + target;
        }
        for (Tag tag : tagList) {
            if (tag.kind().equals(target)) {
                found.append(tag);
            }
        }
        return found.toArray(new Tag[found.length()]);
    }

    /**
     * Return throws tags in this comment.
     */
    ThrowsTag[] throwsTags() {
        ListBuffer<ThrowsTag> found = new ListBuffer<ThrowsTag>();
        for (Tag next : tagList) {
            if (next instanceof ThrowsTag) {
                found.append((ThrowsTag)next);
            }
        }
        return found.toArray(new ThrowsTag[found.length()]);
    }

    /**
     * Return param tags (excluding type param tags) in this comment.
     */
    ParamTag[] paramTags() {
        return paramTags(false);
    }

    /**
     * Return type param tags in this comment.
     */
    ParamTag[] typeParamTags() {
        return paramTags(true);
    }

    /**
     * Return param tags in this comment.  If typeParams is true
     * include only type param tags, otherwise include only ordinary
     * param tags.
     */
    private ParamTag[] paramTags(boolean typeParams) {
        ListBuffer<ParamTag> found = new ListBuffer<ParamTag>();
        for (Tag next : tagList) {
            if (next instanceof ParamTag) {
                ParamTag p = (ParamTag)next;
                if (typeParams == p.isTypeParameter()) {
                    found.append(p);
                }
            }
        }
        return found.toArray(new ParamTag[found.length()]);
    }

    /**
     * Return see also tags in this comment.
     */
    SeeTag[] seeTags() {
        ListBuffer<SeeTag> found = new ListBuffer<SeeTag>();
        for (Tag next : tagList) {
            if (next instanceof SeeTag) {
                found.append((SeeTag)next);
            }
        }
        return found.toArray(new SeeTag[found.length()]);
    }

    /**
     * Return serialField tags in this comment.
     */
    SerialFieldTag[] serialFieldTags() {
        ListBuffer<SerialFieldTag> found = new ListBuffer<SerialFieldTag>();
        for (Tag next : tagList) {
            if (next instanceof SerialFieldTag) {
                found.append((SerialFieldTag)next);
            }
        }
        return found.toArray(new SerialFieldTag[found.length()]);
    }

    /**
     * Return array of tags with text and inline See Tags for a Doc comment.
     */
    static Tag[] getInlineTags(DocImpl holder, String inlinetext) {
        ListBuffer<Tag> taglist = new ListBuffer<Tag>();
        int delimend = 0, textstart = 0, len = inlinetext.length();
        boolean inPre = false;
        DocEnv docenv = holder.env;

        if (len == 0) {
            return taglist.toArray(new Tag[taglist.length()]);
        }
        while (true) {
            int linkstart;
            if ((linkstart = inlineTagFound(holder, inlinetext,
                                            textstart)) == -1) {
                taglist.append(new TagImpl(holder, "Text",
                                           inlinetext.substring(textstart)));
                break;
            } else {
                inPre = scanForPre(inlinetext, textstart, linkstart, inPre);
                int seetextstart = linkstart;
                for (int i = linkstart; i < inlinetext.length(); i++) {
                    char c = inlinetext.charAt(i);
                    if (Character.isWhitespace(c) ||
                        c == '}') {
                        seetextstart = i;
                        break;
                     }
                }
                String linkName = inlinetext.substring(linkstart+2, seetextstart);
                if (!(inPre && (linkName.equals("code") || linkName.equals("literal")))) {
                    //Move past the white space after the inline tag name.
                    while (Character.isWhitespace(inlinetext.
                                                      charAt(seetextstart))) {
                        if (inlinetext.length() <= seetextstart) {
                            taglist.append(new TagImpl(holder, "Text",
                                                       inlinetext.substring(textstart, seetextstart)));
                            docenv.warning(holder,
                                           "tag.Improper_Use_Of_Link_Tag",
                                           inlinetext);
                            return taglist.toArray(new Tag[taglist.length()]);
                        } else {
                            seetextstart++;
                        }
                    }
                }
                taglist.append(new TagImpl(holder, "Text",
                                           inlinetext.substring(textstart, linkstart)));
                textstart = seetextstart;   // this text is actually seetag
                if ((delimend = findInlineTagDelim(inlinetext, textstart)) == -1) {
                    //Missing closing '}' character.
                    // store the text as it is with the {@link.
                    taglist.append(new TagImpl(holder, "Text",
                                               inlinetext.substring(textstart)));
                    docenv.warning(holder,
                                   "tag.End_delimiter_missing_for_possible_SeeTag",
                                   inlinetext);
                    return taglist.toArray(new Tag[taglist.length()]);
                } else {
                    //Found closing '}' character.
                    if (linkName.equals("see")
                           || linkName.equals("link")
                           || linkName.equals("linkplain")) {
                        taglist.append( new SeeTagImpl(holder, "@" + linkName,
                              inlinetext.substring(textstart, delimend)));
                    } else {
                        taglist.append( new TagImpl(holder, "@" + linkName,
                              inlinetext.substring(textstart, delimend)));
                    }
                    textstart = delimend + 1;
                }
            }
            if (textstart == inlinetext.length()) {
                break;
            }
        }
        return taglist.toArray(new Tag[taglist.length()]);
    }

    /** regex for case-insensitive match for {@literal <pre> } and  {@literal </pre> }. */
    private static final Pattern prePat = Pattern.compile("(?i)<(/?)pre>");

    private static boolean scanForPre(String inlinetext, int start, int end, boolean inPre) {
        Matcher m = prePat.matcher(inlinetext).region(start, end);
        while (m.find()) {
            inPre = m.group(1).isEmpty();
        }
        return inPre;
    }

    /**
     * Recursively find the index of the closing '}' character for an inline tag
     * and return it.  If it can't be found, return -1.
     * @param inlineText the text to search in.
     * @param searchStart the index of the place to start searching at.
     * @return the index of the closing '}' character for an inline tag.
     * If it can't be found, return -1.
     */
    private static int findInlineTagDelim(String inlineText, int searchStart) {
        int delimEnd, nestedOpenBrace;
        if ((delimEnd = inlineText.indexOf("}", searchStart)) == -1) {
            return -1;
        } else if (((nestedOpenBrace = inlineText.indexOf("{", searchStart)) != -1) &&
            nestedOpenBrace < delimEnd){
            //Found a nested open brace.
            int nestedCloseBrace = findInlineTagDelim(inlineText, nestedOpenBrace + 1);
            return (nestedCloseBrace != -1) ?
                findInlineTagDelim(inlineText, nestedCloseBrace + 1) :
                -1;
        } else {
            return delimEnd;
        }
    }

    /**
     * Recursively search for the characters '{', '@', followed by
     * name of inline tag and white space,
     * if found
     *    return the index of the text following the white space.
     * else
     *    return -1.
     */
    private static int inlineTagFound(DocImpl holder, String inlinetext, int start) {
        DocEnv docenv = holder.env;
        int linkstart = inlinetext.indexOf("{@", start);
        if (start == inlinetext.length() || linkstart == -1) {
            return -1;
        } else if (inlinetext.indexOf('}', linkstart) == -1) {
            //Missing '}'.
            docenv.warning(holder, "tag.Improper_Use_Of_Link_Tag",
                    inlinetext.substring(linkstart, inlinetext.length()));
            return -1;
        } else {
            return linkstart;
        }
    }


    /**
     * Return array of tags for the locale specific first sentence in the text.
     */
    static Tag[] firstSentenceTags(DocImpl holder, String text) {
        DocLocale doclocale = holder.env.doclocale;
        return getInlineTags(holder,
                             doclocale.localeSpecificFirstSentence(holder, text));
    }

    /**
     * Return text for this Doc comment.
     */
    @Override
    public String toString() {
        return text;
    }
}
