/*
 * Copyright (c) 2006, 2021 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,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation
//
package org.eclipse.persistence.jpa.tests.jpql.parser;

import org.eclipse.persistence.jpa.jpql.WordParser;
import org.eclipse.persistence.jpa.jpql.parser.*;
import org.eclipse.persistence.jpa.jpql.tools.model.IJPQLQueryFormatter.IdentifierStyle;
import static org.eclipse.persistence.jpa.jpql.parser.AbstractExpression.*;
import static org.eclipse.persistence.jpa.jpql.parser.Expression.*;
import static org.junit.Assert.*;

/**
 * This builder creates the parsed tree representation of a JPQL query and verifies the generated
 * strings ({@link org.eclipse.persistence.jpa.jpql.parser.Expression#toActualText()
 * Expression.toActualText()} and {@link org.eclipse.persistence.jpa.jpql.parser.Expression#toParsedText()
 * Expression.toParsedText()}) were generated correctly.
 *
 * @version 2.4
 * @since 2.3
 * @author Pascal Filion
 */
@SuppressWarnings({"nls", "unused" /* For the extra import statement, see bug 330740 */})
public final class JPQLQueryBuilder {

    /**
     * Parses the given JPQL query and tests its generated string with the given query, which will be
     * formatted first.
     *
     * @param jpqlQuery The JPQL query to parse into a parsed tree
     * @param jpqlGrammar The JPQL grammar that defines how to parse the given JPQL query
     * @param tolerant Determines if the parsing system should be tolerant, meaning if it should try
     * to parse invalid or incomplete queries
     * @return The parsed tree representation of the given JPQL query
     */
    public static JPQLExpression buildQuery(String jpqlQuery, JPQLGrammar jpqlGrammar, boolean tolerant) {
        return buildQuery(jpqlQuery, jpqlGrammar, JPQLQueryStringFormatter.DEFAULT, tolerant);
    }

    /**
     * Parses the given JPQL query and tests its generated string with the given query, which will be
     * formatted first.
     *
     * @param jpqlQuery The JPQL query to parse into a parsed tree
     * @param jpqlGrammar The JPQL grammar that defines how to parse the given JPQL query
     * @param formatter This formatter is used to personalized the formatting of the JPQL query
     * before it is used to test the generated string
     * @param tolerant Determines if the parsing system should be tolerant, meaning if it should try
     * to parse invalid or incomplete queries
     * @return The parsed tree representation of the given JPQL query
     */
    public static JPQLExpression buildQuery(String jpqlQuery,
                                            JPQLGrammar jpqlGrammar,
                                            JPQLQueryStringFormatter formatter,
                                            boolean tolerant) {

        return buildQuery(jpqlQuery, jpqlGrammar, JPQLStatementBNF.ID, formatter, tolerant);
    }

    /**
     * Parses the given JPQL query and tests its generated string with the given query, which will be
     * formatted first.
     *
     * @param jpqlQuery The JPQL query to parse into a parsed tree
     * @param jpqlGrammar The JPQL grammar that defines how to parse the given JPQL query
     * @param jpqlQueryBNFId The unique identifier of the {@link JPQLQueryBNF JPQLQueryBNF}
     * @param tolerant Determines if the parsing system should be tolerant, meaning if it should try
     * to parse invalid or incomplete queries
     * @return The parsed tree representation of the given JPQL query
     */
    public static JPQLExpression buildQuery(String jpqlQuery,
                                            JPQLGrammar jpqlGrammar,
                                            String jpqlQueryBNFId,
                                            boolean tolerant) {

        return buildQuery(jpqlQuery, jpqlGrammar, jpqlQueryBNFId, JPQLQueryStringFormatter.DEFAULT, tolerant);
    }

    /**
     * Parses the given JPQL query and tests its generated string with the given query, which will be
     * formatted first. Both the parsed and actual generated strings will be tested.
     *
     * @param jpqlQuery The JPQL query to parse into a parsed tree
     * @param jpqlGrammar The JPQL grammar that defines how to parse the given JPQL query
     * @param jpqlQueryBNFId The unique identifier of the {@link JPQLQueryBNF JPQLQueryBNF}
     * @param formatter This formatter is used to personalized the formatting of the JPQL query
     * before it is used to test the generated string
     * @param tolerant Determines if the parsing system should be tolerant, meaning if it should try
     * to parse invalid or incomplete queries
     * @return The parsed tree representation of the given JPQL query
     */
    public static JPQLExpression buildQuery(String jpqlQuery,
                                            JPQLGrammar jpqlGrammar,
                                            String jpqlQueryBNFId,
                                            JPQLQueryStringFormatter formatter,
                                            boolean tolerant) {

        // Format the JPQL query to reflect how the parsed tree outputs the query back as a string
        String parsedJPQLQuery = toParsedText(jpqlQuery, jpqlGrammar);
        String actualJPQLQuery = toActualText(jpqlQuery, jpqlGrammar);

        // Format the JPQL query with this formatter so the invoker can tweak the default formatting
        parsedJPQLQuery = formatter.format(parsedJPQLQuery);
        actualJPQLQuery = formatter.format(actualJPQLQuery);

        // Parse the JPQL query
        JPQLExpression jpqlExpression = new JPQLExpression(jpqlQuery, jpqlGrammar, jpqlQueryBNFId, tolerant);

        // Make sure the JPQL query was correctly parsed and the
        // generated string matches the original JPQL query
        assertEquals(parsedJPQLQuery, jpqlExpression.toParsedText());
        assertEquals(actualJPQLQuery, jpqlExpression.toActualText());

        // If the JPQL query is parsed with tolerance turned off, then the query should
        // be completely parsed and there should not be any unknown ending statement
        if (!tolerant && (jpqlQueryBNFId == JPQLStatementBNF.ID)) {
            assertFalse(
                "A valid JPQL query cannot have an unknown ending fragment:" + jpqlQueryBNFId,
                jpqlExpression.hasUnknownEndingStatement()
            );
        }

        return jpqlExpression;
    }

    /**
     * Formats the given JPQL query by converting it to what
     * {@link Expression#toActualText() Expression.toActualText()} would return.
     * <p>
     * For instance, "Select e   From Employee e" will be converted to "Select e From Employee e".
     *
     * @param jpqlQuery The string to format
     * @param jpqlGrammar The {@link JPQLGrammar} is used to properly format the string
     * @return The converted string
     * @see #toParsedText(String, JPQLGrammar)
     * @see #toText(String, JPQLGrammar, boolean, IdentifierStyle)
     */
    public static String toActualText(String jpqlQuery, JPQLGrammar jpqlGrammar) {
        return toText(jpqlQuery, jpqlGrammar, true, IdentifierStyle.UPPERCASE);
    }

    /**
     * Formats the given JPQL query by converting it to what
     * {@link Expression#toParsedText() Expression.toParsedText()}  would return.
     * <p>
     * For instance, "Select e   From Employee e" will be converted to "SELECT e FROM Employee e".
     *
     * @param jpqlQuery The string to format
     * @param jpqlGrammar The {@link JPQLGrammar} is used to properly format the string
     * @return The formatted JPQL query
     * @see #toActualText(String, JPQLGrammar)
     * @see #toText(String, JPQLGrammar, boolean, IdentifierStyle)
     */
    public static String toParsedText(String jpqlQuery, JPQLGrammar jpqlGrammar) {
        return toText(jpqlQuery, jpqlGrammar, false, IdentifierStyle.UPPERCASE);
    }

    /**
     * Formats the given JPQL query by replacing multiple whitespace with a single whitespace. The
     * JPQL identifiers will be converted to uppercase if <em>exactMatch</em> is <code>true</code>
     * otherwise they will remain unchanged.
     *
     * @param jpqlQuery The string to format
     * @param jpqlGrammar The {@link JPQLGrammar} is used to properly format the string
     * @param exactMatch
     * @param style
     * @return The formatted JPQL query
     * @see #toActualText(String, JPQLGrammar)
     * @see #toParsedText(String, JPQLGrammar)
     */
    public static String toText(String jpqlQuery,
                                JPQLGrammar jpqlGrammar,
                                boolean exactMatch,
                                IdentifierStyle style) {

        ExpressionRegistry registry = jpqlGrammar.getExpressionRegistry();
        StringBuilder sb = new StringBuilder();
        WordParser wordParser = new WordParser(jpqlQuery);
        boolean singleQuoteParsed = false;
        Boolean fromClause = null;
        int whitespaceParsed = 0;

        for (int index = 0, count = jpqlQuery.length(); index < count; index++) {

            char character = jpqlQuery.charAt(index);

            // '
            if (character == SINGLE_QUOTE) {

                // Entering string literal
                if (!singleQuoteParsed) {
                    singleQuoteParsed = true;
                }
                else {
                    // Make sure the single quote is not escaped
                    char nextCharacter = (index + 1 < count) ? jpqlQuery.charAt(index + 1) : '\0';

                    // Exiting the string literal
                    if (nextCharacter != SINGLE_QUOTE) {
                        singleQuoteParsed = false;
                    }
                    // Skip the escaped '
                    else {
                        sb.append(character);
                        index++;
                    }
                }

                whitespaceParsed  = 0;
            }
            // Anything outside of string literal
            else if (!singleQuoteParsed) {

                // Will skip whitespace after the first one but not inside string literals
                if (Character.isWhitespace(character)) {

                    // Leading whitespace is always removed
                    if (sb.length() == 0) {
                        continue;
                    }

                    // Make sure the whitespace is a real space
                    character = SPACE;

                    // '( ' will always be converted to '('
                    char previousCharacter = (index > 0) ? jpqlQuery.charAt(index - 1) : '\0';

                    if (previousCharacter == LEFT_PARENTHESIS) {

                        // Skip any subsequent whitespace
                        while (index < count) {
                            previousCharacter = jpqlQuery.charAt(index + 1);
                            if (!Character.isWhitespace(previousCharacter)) {
                                break;
                            }
                            index++;
                        }

                        // Function without a closing parenthesis should have a whitespace after (
                        // Example: "... ABS( FROM Employee e"
                        if (!wordParser.startsWithIdentifier(FROM,     index + 1) &&
                            !wordParser.startsWithIdentifier(WHERE,    index + 1) &&
                            !wordParser.startsWithIdentifier(GROUP_BY, index + 1) &&
                            !wordParser.startsWithIdentifier(ORDER_BY, index + 1)) {

                            continue;
                        }
                    }

                    whitespaceParsed++;

                    // Capitalize JPQL identifiers
                    if (!exactMatch && (whitespaceParsed == 1)) {
                        String identifier = wordParser.partialWord(index);
                        int length = identifier.length();

                        if ((length > 0) && registry.isIdentifier(identifier)) {

                            // The word "ORDER"/"GROUP" is not the entity name but the identifier ORDER BY
                            if ((fromClause == Boolean.TRUE) &&
                                (identifier.equalsIgnoreCase("ORDER") ||
                                 identifier.equalsIgnoreCase("GROUP")) &&
                                (wordParser.startsWithIgnoreCase(ORDER_BY, index - 5) ||
                                 wordParser.startsWithIgnoreCase(GROUP_BY, index - 5))) {

                                fromClause = null;
                            }

                            // Special case where Order/Group should not be capitalized when it's the entity name
                            if (!((fromClause == Boolean.TRUE) &&
                                  (identifier.equalsIgnoreCase("ORDER") ||
                                   identifier.equalsIgnoreCase("GROUP")))) {

                                identifier = style.formatIdentifier(identifier);
                                int offset = sb.length();
                                sb.replace(offset - length, offset, identifier);
                            }

                            // The FROM clause should be parsed soon
                            if ((fromClause == null) && SELECT.equalsIgnoreCase(identifier)) {
                                fromClause = Boolean.FALSE;
                            }
                            // Entering the FROM clause
                            else if ((fromClause == Boolean.FALSE) && FROM.equalsIgnoreCase(identifier)) {
                                fromClause = Boolean.TRUE;
                            }
                            // Exiting the FROM clause
                            else if ((fromClause == Boolean.TRUE) &&
                                     (WHERE  .equalsIgnoreCase(identifier) ||
                                      HAVING .equalsIgnoreCase(identifier) ||
                                      "ORDER".equalsIgnoreCase(identifier) ||
                                      "GROUP".equalsIgnoreCase(identifier))) {

                                fromClause = null;
                            }
                        }
                    }

                    // Skip any subsequent whitespace
                    if (whitespaceParsed > 1) {
                        continue;
                    }
                }
                // '('
                else if (character == LEFT_PARENTHESIS) {
                    String previousWord = wordParser.partialWord(index - whitespaceParsed);

                    // Remove the previous character, which is a whitespace and only if
                    // it's after a function like "ABS (", which will be converted to "ABS("
                    // but "WHERE (" will remain "WHERE (" (same with NEW)
                    if (!NEW.equalsIgnoreCase(previousWord)) {

                        if ((whitespaceParsed > 0) && !previousWord.equalsIgnoreCase(NEW)) {
                            IdentifierRole role = registry.getIdentifierRole(previousWord);

                            if ((role == IdentifierRole.FUNCTION) || IN.equalsIgnoreCase(previousWord)) {
                                int offset = sb.length();
                                sb.delete(offset - 1, offset);
                            }
                        }
                        else {
                            int length = previousWord.length();

                            // Capitalize JPQL identifiers
                            if (!exactMatch && (length > 0) && registry.isIdentifier(previousWord)) {
                                previousWord = style.formatIdentifier(previousWord);
                                int offset = sb.length();
                                sb.replace(offset - length, offset, previousWord);
                            }
                        }
                    }

                    whitespaceParsed = 0;
                }
                // ')'
                // ','
                // Remove any whitespace before ')' or ','
                else if (character == RIGHT_PARENTHESIS ||
                         character == COMMA) {

                    if (whitespaceParsed > 0) {
                        int offset = sb.length();
                        sb.delete(offset - 1, offset);
                    }
                    // Capitalize JPQL identifiers
                    else if (!exactMatch) {
                        String identifier = wordParser.partialWord(index);
                        int length = identifier.length();

                        if ((length > 0) && registry.isIdentifier(identifier)) {
                            identifier = style.formatIdentifier(identifier);
                            int offset = sb.length();
                            sb.replace(offset - length, offset, identifier);
                        }
                    }

                    // Add a whitespace after ','
                    if ((character == COMMA) && (index + 1 < count)) {
                        char nextCharacter = jpqlQuery.charAt(index + 1);

                        // But not if the next character is ')' or ','
                        if ((nextCharacter != COMMA) &&
                            (nextCharacter != RIGHT_PARENTHESIS) &&
                            !Character.isWhitespace(nextCharacter)) {

                            sb.append(character);
                            character = SPACE;
                        }
                    }

                    whitespaceParsed = 0;
                }
                // Add a whitespace before and after *, /
                else if ((character == '*') ||
                         (character == '/')) {

                    // Add a whitespace before
                    if (whitespaceParsed == 0) {
                        sb.append(' ');
                    }

                    // Add a whitespace after
                    if (index + 1 < count) {
                        char nextCharacter = jpqlQuery.charAt(index + 1);
                        if (!Character.isWhitespace(nextCharacter)) {
                            sb.append(character);
                            character = SPACE;
                        }
                    }

                    whitespaceParsed = 0;
                }
                // !=
                else if (character == '!') {

                    if (index + 1 < count) {
                        char nextCharacter = jpqlQuery.charAt(index + 1);

                        // != needs to have whitespace around it
                        if ((nextCharacter == '=') && (whitespaceParsed == 0)) {
                            sb.append(' ');
                        }
                    }

                    whitespaceParsed = 0;
                }
                // Add a whitespace before and after <, <=, =, >=, >, <>, !=
                else if ((character == '=') ||
                         (character == '<') ||
                         (character == '>')) {

                    char previousCharacter = jpqlQuery.charAt(index - 1);

                    if (character == '=' &&
                        previousCharacter == '!') {

                        // Don't do anything for !=
                    }
                    // Add a whitespace before
                    else if ((previousCharacter != '>') &&
                             (previousCharacter != '<') &&
                             (whitespaceParsed == 0)) {

                        sb.append(' ');
                    }

                    // Add a whitespace after
                    if (index + 1 < count) {
                        char nextCharacter = jpqlQuery.charAt(index + 1);

                        // Don't add a whitespace if it's <=, >=, <>, !=
                        if ((nextCharacter != '=') &&
                            (nextCharacter != '>') &&
                            !Character.isWhitespace(nextCharacter)) {

                            sb.append(character);
                            character = SPACE;
                        }
                    }

                    whitespaceParsed = 0;
                }
                else {
                    whitespaceParsed = 0;
                }
            }

            sb.append(character);

            // At the end of the query, make sure the last JPQL identifier is capitalized if required
            if (!exactMatch &&
                (index + 1 == count) &&
                (character != SINGLE_QUOTE) &&
                (whitespaceParsed == 0)) {

                String previousWord = wordParser.partialWord(index + 1);
                int length = previousWord.length();

                // Capitalize JPQL identifiers
                if ((length > 0) && registry.isIdentifier(previousWord)) {
                    previousWord = style.formatIdentifier(previousWord);
                    int offset = sb.length();
                    sb.replace(offset - length, offset, previousWord);
                }
            }
        }

        return sb.toString();
    }
}
