////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2017 the original author or authors.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
////////////////////////////////////////////////////////////////////////////////

package com.puppycrawl.tools.checkstyle.utils;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

import com.google.common.collect.ImmutableMap;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.DetailNode;
import com.puppycrawl.tools.checkstyle.api.JavadocTokenTypes;
import com.puppycrawl.tools.checkstyle.api.TextBlock;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
import com.puppycrawl.tools.checkstyle.checks.javadoc.InvalidJavadocTag;
import com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocTag;
import com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocTagInfo;
import com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocTags;
import com.puppycrawl.tools.checkstyle.checks.javadoc.utils.BlockTagUtils;
import com.puppycrawl.tools.checkstyle.checks.javadoc.utils.InlineTagUtils;
import com.puppycrawl.tools.checkstyle.checks.javadoc.utils.TagInfo;

/**
 * Contains utility methods for working with Javadoc.
 * @author Lyle Hanson
 */
public final class JavadocUtils {

    /**
     * The type of Javadoc tag we want returned.
     */
    public enum JavadocTagType {
        /** Block type. */
        BLOCK,
        /** Inline type. */
        INLINE,
        /** All validTags. */
        ALL
    }

    /** Maps from a token name to value. */
    private static final ImmutableMap<String, Integer> TOKEN_NAME_TO_VALUE;
    /** Maps from a token value to name. */
    private static final String[] TOKEN_VALUE_TO_NAME;

    /** Exception message for unknown JavaDoc token id. */
    private static final String UNKNOWN_JAVADOC_TOKEN_ID_EXCEPTION_MESSAGE = "Unknown javadoc"
            + " token id. Given id: ";

    /** Newline pattern. */
    private static final Pattern NEWLINE = Pattern.compile("\n");

    /** Return pattern. */
    private static final Pattern RETURN = Pattern.compile("\r");

    /** Tab pattern. */
    private static final Pattern TAB = Pattern.compile("\t");

    // Using reflection gets all token names and values from JavadocTokenTypes class
    // and saves to TOKEN_NAME_TO_VALUE and TOKEN_VALUE_TO_NAME collections.
    static {
        final ImmutableMap.Builder<String, Integer> builder = ImmutableMap.builder();

        final Field[] fields = JavadocTokenTypes.class.getDeclaredFields();

        String[] tempTokenValueToName = CommonUtils.EMPTY_STRING_ARRAY;

        for (final Field field : fields) {

            // Only process public int fields.
            if (!Modifier.isPublic(field.getModifiers())
                    || field.getType() != Integer.TYPE) {
                continue;
            }

            final String name = field.getName();

            final int tokenValue = TokenUtils.getIntFromField(field, name);
            builder.put(name, tokenValue);
            if (tokenValue > tempTokenValueToName.length - 1) {
                final String[] temp = new String[tokenValue + 1];
                System.arraycopy(tempTokenValueToName, 0, temp, 0, tempTokenValueToName.length);
                tempTokenValueToName = temp;
            }
            if (tokenValue == -1) {
                tempTokenValueToName[0] = name;
            }
            else {
                tempTokenValueToName[tokenValue] = name;
            }
        }

        TOKEN_NAME_TO_VALUE = builder.build();
        TOKEN_VALUE_TO_NAME = tempTokenValueToName;
    }

    /** Prevent instantiation. */
    private JavadocUtils() {
    }

    /**
     * Gets validTags from a given piece of Javadoc.
     * @param textBlock
     *        the Javadoc comment to process.
     * @param tagType
     *        the type of validTags we're interested in
     * @return all standalone validTags from the given javadoc.
     */
    public static JavadocTags getJavadocTags(TextBlock textBlock,
            JavadocTagType tagType) {

        final boolean getBlockTags = tagType == JavadocTagType.ALL
                                         || tagType == JavadocTagType.BLOCK;
        final boolean getInlineTags = tagType == JavadocTagType.ALL
                                          || tagType == JavadocTagType.INLINE;

        final List<TagInfo> tags = new ArrayList<>();

        if (getBlockTags) {
            tags.addAll(BlockTagUtils.extractBlockTags(textBlock.getText()));
        }

        if (getInlineTags) {
            tags.addAll(InlineTagUtils.extractInlineTags(textBlock.getText()));
        }

        final List<JavadocTag> validTags = new ArrayList<>();
        final List<InvalidJavadocTag> invalidTags = new ArrayList<>();

        for (TagInfo tag : tags) {
            final int col = tag.getPosition().getColumn();

            // Add the starting line of the comment to the line number to get the actual line number
            // in the source.
            // Lines are one-indexed, so need a off-by-one correction.
            final int line = textBlock.getStartLineNo() + tag.getPosition().getLine() - 1;

            if (JavadocTagInfo.isValidName(tag.getName())) {
                validTags.add(
                    new JavadocTag(line, col, tag.getName(), tag.getValue()));
            }
            else {
                invalidTags.add(new InvalidJavadocTag(line, col, tag.getName()));
            }
        }

        return new JavadocTags(validTags, invalidTags);
    }

    /**
     * Checks that commentContent starts with '*' javadoc comment identifier.
     * @param commentContent
     *        content of block comment
     * @return true if commentContent starts with '*' javadoc comment
     *         identifier.
     */
    public static boolean isJavadocComment(String commentContent) {
        boolean result = false;

        if (!commentContent.isEmpty()) {
            final char docCommentIdentificator = commentContent.charAt(0);
            result = docCommentIdentificator == '*';
        }

        return result;
    }

    /**
     * Checks block comment content starts with '*' javadoc comment identifier.
     * @param blockCommentBegin
     *        block comment AST
     * @return true if block comment content starts with '*' javadoc comment
     *         identifier.
     */
    public static boolean isJavadocComment(DetailAST blockCommentBegin) {
        final String commentContent = getBlockCommentContent(blockCommentBegin);
        return isJavadocComment(commentContent) && isCorrectJavadocPosition(blockCommentBegin);
    }

    /**
     * Gets content of block comment.
     * @param blockCommentBegin
     *        block comment AST.
     * @return content of block comment.
     */
    private static String getBlockCommentContent(DetailAST blockCommentBegin) {
        final DetailAST commentContent = blockCommentBegin.getFirstChild();
        return commentContent.getText();
    }

    /**
     * Get content of Javadoc comment.
     * @param javadocCommentBegin
     *        Javadoc comment AST
     * @return content of Javadoc comment.
     */
    public static String getJavadocCommentContent(DetailAST javadocCommentBegin) {
        final DetailAST commentContent = javadocCommentBegin.getFirstChild();
        return commentContent.getText().substring(1);
    }

    /**
     * Returns the first child token that has a specified type.
     * @param detailNode
     *        Javadoc AST node
     * @param type
     *        the token type to match
     * @return the matching token, or null if no match
     */
    public static DetailNode findFirstToken(DetailNode detailNode, int type) {
        DetailNode returnValue = null;
        DetailNode node = getFirstChild(detailNode);
        while (node != null) {
            if (node.getType() == type) {
                returnValue = node;
                break;
            }
            node = getNextSibling(node);
        }
        return returnValue;
    }

    /**
     * Gets first child node of specified node.
     *
     * @param node DetailNode
     * @return first child
     */
    public static DetailNode getFirstChild(DetailNode node) {
        DetailNode resultNode = null;

        if (node.getChildren().length > 0) {
            resultNode = node.getChildren()[0];
        }
        return resultNode;
    }

    /**
     * Checks whether node contains any node of specified type among children on any deep level.
     *
     * @param node DetailNode
     * @param type token type
     * @return true if node contains any node of type type among children on any deep level.
     */
    public static boolean containsInBranch(DetailNode node, int type) {
        boolean result = true;
        DetailNode curNode = node;
        while (type != curNode.getType()) {
            DetailNode toVisit = getFirstChild(curNode);
            while (curNode != null && toVisit == null) {
                toVisit = getNextSibling(curNode);
                if (toVisit == null) {
                    curNode = curNode.getParent();
                }
            }

            if (curNode == toVisit) {
                result = false;
                break;
            }

            curNode = toVisit;
        }
        return result;
    }

    /**
     * Gets next sibling of specified node.
     *
     * @param node DetailNode
     * @return next sibling.
     */
    public static DetailNode getNextSibling(DetailNode node) {
        DetailNode nextSibling = null;
        final DetailNode parent = node.getParent();
        if (parent != null) {
            final int nextSiblingIndex = node.getIndex() + 1;
            final DetailNode[] children = parent.getChildren();
            if (nextSiblingIndex <= children.length - 1) {
                nextSibling = children[nextSiblingIndex];
            }
        }
        return nextSibling;
    }

    /**
     * Gets next sibling of specified node with the specified type.
     *
     * @param node DetailNode
     * @param tokenType javadoc token type
     * @return next sibling.
     */
    public static DetailNode getNextSibling(DetailNode node, int tokenType) {
        DetailNode nextSibling = getNextSibling(node);
        while (nextSibling != null && nextSibling.getType() != tokenType) {
            nextSibling = getNextSibling(nextSibling);
        }
        return nextSibling;
    }

    /**
     * Gets previous sibling of specified node.
     * @param node DetailNode
     * @return previous sibling
     */
    public static DetailNode getPreviousSibling(DetailNode node) {
        DetailNode previousSibling = null;
        final int previousSiblingIndex = node.getIndex() - 1;
        if (previousSiblingIndex >= 0) {
            final DetailNode parent = node.getParent();
            final DetailNode[] children = parent.getChildren();
            previousSibling = children[previousSiblingIndex];
        }
        return previousSibling;
    }

    /**
     * Returns the name of a token for a given ID.
     * @param id
     *        the ID of the token name to get
     * @return a token name
     */
    public static String getTokenName(int id) {
        final String name;
        if (id == JavadocTokenTypes.EOF) {
            name = "EOF";
        }
        else if (id > TOKEN_VALUE_TO_NAME.length - 1) {
            throw new IllegalArgumentException(UNKNOWN_JAVADOC_TOKEN_ID_EXCEPTION_MESSAGE + id);
        }
        else {
            name = TOKEN_VALUE_TO_NAME[id];
            if (name == null) {
                throw new IllegalArgumentException(UNKNOWN_JAVADOC_TOKEN_ID_EXCEPTION_MESSAGE + id);
            }
        }
        return name;
    }

    /**
     * Returns the ID of a token for a given name.
     * @param name
     *        the name of the token ID to get
     * @return a token ID
     */
    public static int getTokenId(String name) {
        final Integer id = TOKEN_NAME_TO_VALUE.get(name);
        if (id == null) {
            throw new IllegalArgumentException("Unknown javadoc token name. Given name " + name);
        }
        return id;
    }

    /**
     * Gets tag name from javadocTagSection.
     *
     * @param javadocTagSection to get tag name from.
     * @return name, of the javadocTagSection's tag.
     */
    public static String getTagName(DetailNode javadocTagSection) {
        final String javadocTagName;
        if (javadocTagSection.getType() == JavadocTokenTypes.JAVADOC_INLINE_TAG) {
            javadocTagName = getNextSibling(
                    getFirstChild(javadocTagSection)).getText();
        }
        else {
            javadocTagName = getFirstChild(javadocTagSection).getText();
        }
        return javadocTagName;
    }

    /**
     * Replace all control chars with escaped symbols.
     * @param text the String to process.
     * @return the processed String with all control chars escaped.
     */
    public static String escapeAllControlChars(String text) {
        final String textWithoutNewlines = NEWLINE.matcher(text).replaceAll("\\\\n");
        final String textWithoutReturns = RETURN.matcher(textWithoutNewlines).replaceAll("\\\\r");
        return TAB.matcher(textWithoutReturns).replaceAll("\\\\t");
    }

    /**
     * Checks Javadoc comment it's in right place.
     * <p>From Javadoc util documentation:
     * "Placement of comments - Documentation comments are recognized only when placed
     * immediately before class, interface, constructor, method, field or annotation field
     * declarations -- see the class example, method example, and field example.
     * Documentation comments placed in the body of a method are ignored."</p>
     * <p>If there are many documentation comments per declaration statement,
     * only the last one will be recognized.</p>
     *
     * @param blockComment Block comment AST
     * @return true if Javadoc is in right place
     * @see <a href="https://docs.oracle.com/javase/8/docs/technotes/tools/unix/javadoc.html">
     *     Javadoc util documentation</a>
     */
    private static boolean isCorrectJavadocPosition(DetailAST blockComment) {
        // We must be sure that after this one there are no other documentation comments.
        DetailAST sibling = blockComment.getNextSibling();
        while (sibling != null) {
            if (sibling.getType() == TokenTypes.BLOCK_COMMENT_BEGIN) {
                if (isJavadocComment(getBlockCommentContent(sibling))) {
                    // Found another javadoc comment, so this one should be ignored.
                    break;
                }
                sibling = sibling.getNextSibling();
            }
            else if (sibling.getType() == TokenTypes.SINGLE_LINE_COMMENT) {
                sibling = sibling.getNextSibling();
            }
            else {
                // Annotation, declaration or modifier is here. Do not check further.
                sibling = null;
            }
        }
        return sibling == null
            && (BlockCommentPosition.isOnType(blockComment)
                || BlockCommentPosition.isOnMember(blockComment));
    }
}
