/*
 * 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.jpql.parser;

import java.util.Collection;
import java.util.List;
import org.eclipse.persistence.jpa.jpql.ExpressionTools;
import org.eclipse.persistence.jpa.jpql.JPAVersion;
import org.eclipse.persistence.jpa.jpql.WordParser;

/**
 * A <code>JPQLExpression</code> is the root of the parsed tree representation of a JPQL query. The
 * query is parsed based on what was registered in the {@link JPQLGrammar}'s {@link ExpressionRegistry}.
 * <p>
 * A JPQL statement may be either a <b>SELECT</b> statement, an <b>UPDATE</b> statement, or a
 * <b>DELETE FROM</b> statement.
 *
 * <div><b>BNF:</b> <code>QL_statement ::= {@link SelectStatement select_statement} |
 *                                                {@link UpdateStatement update_statement} |
 *                                                {@link DeleteStatement delete_statement}</code></div>
 * <p>
 * It is possible to parse a portion of a JPQL query. The ID of the {@link JPQLQueryBNF} is used to
 * parse that portion and {@link #getQueryStatement()} then returns only the parsed tree representation
 * of that JPQL fragment.
 *
 * @version 2.5
 * @since 2.3
 * @author Pascal Filion
 */
@SuppressWarnings("nls")
public final class JPQLExpression extends AbstractExpression {

    /**
     * The JPQL grammar that defines how to parse a JPQL query.
     */
    private JPQLGrammar jpqlGrammar;

    /**
     * By default, this is {@link JPQLStatementBNF#ID} but it can be any other unique identifier of
     * a {@link JPQLQueryBNF} when a portion of a JPQL query needs to be parsed.
     */
    private String queryBNFId;

    /**
     * The tree representation of the query.
     */
    private AbstractExpression queryStatement;

    /**
     * Determines if the parsing system should be tolerant, meaning if it should try to parse invalid
     * or incomplete queries.
     */
    private boolean tolerant;

    /**
     * If the expression could not be fully parsed, meaning some unknown text is trailing the query,
     * this will contain it.
     */
    private AbstractExpression unknownEndingStatement;

    /**
     * Creates a new <code>JPQLExpression</code>, which is the root of the JPQL parsed tree.
     *
     * @param query The string representation of the JPQL query to parse
     * @param jpqlGrammar The JPQL grammar that defines how to parse a JPQL query
     */
    public JPQLExpression(CharSequence query, JPQLGrammar jpqlGrammar) {
        this(query, jpqlGrammar, false);
    }

    /**
     * Creates a new <code>JPQLExpression</code>, which is the root of the JPQL parsed tree.
     *
     * @param query The string representation of the JPQL query to parse
     * @param jpqlGrammar The JPQL grammar that defines how to parse a JPQL query
     * @param tolerant Determines if the parsing system should be tolerant, meaning if it should try
     * to parse invalid or incomplete queries
     */
    public JPQLExpression(CharSequence query, JPQLGrammar jpqlGrammar, boolean tolerant) {
        this(query, jpqlGrammar, JPQLStatementBNF.ID, tolerant);
    }

    /**
     * Creates a new <code>JPQLExpression</code> that will parse the given fragment of a JPQL query.
     * This means {@link #getQueryStatement()} will not return a query statement (select, delete or
     * update) but only the parsed tree representation of the fragment if the query BNF can pare it.
     * If the fragment of the JPQL query could not be parsed using the given {@link JPQLQueryBNF},
     * then {@link #getUnknownEndingStatement()} will contain the non-parsable fragment.
     *
     * @param jpqlFragment A fragment of a JPQL query, which is a portion of a complete JPQL query
     * @param jpqlGrammar The JPQL grammar that defines how to parse a JPQL query
     * @param queryBNFId The unique identifier of the {@link org.eclipse.persistence.jpa.jpql.parser.JPQLQueryBNF JPQLQueryBNF}
     * @param tolerant Determines if the parsing system should be tolerant, meaning if it should try
     * to parse invalid or incomplete queries
     * @since 2.4
     */
    public JPQLExpression(CharSequence jpqlFragment,
                          JPQLGrammar jpqlGrammar,
                          String queryBNFId,
                          boolean tolerant) {

        this(jpqlGrammar, queryBNFId, tolerant);
        parse(new WordParser(jpqlFragment), tolerant);
    }

    /**
     * Creates a new <code>JPQLExpression</code>, which is the root of the JPQL parsed tree.
     *
     * @param jpqlGrammar The JPQL grammar that defines how to parse a JPQL query
     * @param tolerant Determines if the parsing system should be tolerant, meaning if it should try
     * to parse invalid or incomplete queries
     */
    private JPQLExpression(JPQLGrammar jpqlGrammar, String queryBNFId, boolean tolerant) {
        super(null);
        this.queryBNFId  = queryBNFId;
        this.tolerant    = tolerant;
        this.jpqlGrammar = jpqlGrammar;
    }

    @Override
    public void accept(ExpressionVisitor visitor) {
        visitor.visit(this);
    }

    @Override
    public void acceptChildren(ExpressionVisitor visitor) {
        getQueryStatement().accept(visitor);
        getUnknownEndingStatement().accept(visitor);
    }

    @Override
    protected void addChildrenTo(Collection<Expression> children) {
        children.add(getQueryStatement());
        children.add(getUnknownEndingStatement());
    }

    @Override
    protected void addOrderedChildrenTo(List<Expression> children) {

        if (queryStatement != null) {
            children.add(queryStatement);
        }

        if (unknownEndingStatement != null) {
            children.add(unknownEndingStatement);
        }
    }

    /**
     * Creates a map of the position of the cursor within each {@link Expression} of the parsed tree.
     *
     * @param actualQuery The actual query is a string representation of the query that may contain
     * extra whitespace
     * @param position The position of the cursor in the actual query, which is used to retrieve the
     * deepest {@link Expression}. The position will be adjusted to fit into the beautified version
     * of the query
     * @return A new {@link QueryPosition}
     */
    public QueryPosition buildPosition(String actualQuery, int position) {

        // Adjust the position by not counting extra whitespace
        position = ExpressionTools.repositionCursor(actualQuery, position, toActualText());

        QueryPosition queryPosition = new QueryPosition(position);
        populatePosition(queryPosition, position);
        return queryPosition;
    }

    /**
     * Returns the deepest {@link Expression} for the given position.
     *
     * @param actualQuery The actual query is the text version of the query that may contain extra
     * whitespace and different formatting than the trim down version generated by the parsed tree
     * @param position The position in the actual query used to retrieve the {@link Expression}
     * @return The {@link Expression} located at the given position in the given query
     */
    public Expression getExpression(String actualQuery, int position) {
        QueryPosition queryPosition = buildPosition(actualQuery, position);
        return queryPosition.getExpression();
    }

    @Override
    public JPQLGrammar getGrammar() {
        return jpqlGrammar;
    }

    @Override
    public JPAVersion getJPAVersion() {
        return jpqlGrammar.getJPAVersion();
    }

    @Override
    public JPQLQueryBNF getQueryBNF() {
        return getQueryBNF(queryBNFId);
    }

    /**
     * Returns the {@link Expression} representing the query, which is either a <b>SELECT</b>, a
     * <b>DELETE</b> or an <b>UPDATE</b> clause.
     *
     * @return The expression representing the Java Persistence query
     */
    public Expression getQueryStatement() {
        if (queryStatement == null) {
            queryStatement = buildNullExpression();
        }
        return queryStatement;
    }

    /**
     * Returns the {@link Expression} that may contain a portion of the query that could not be
     * parsed, this happens when the query is either incomplete or malformed.
     *
     * @return The expression used when the ending of the query is unknown or malformed
     */
    public Expression getUnknownEndingStatement() {
        if (unknownEndingStatement == null) {
            unknownEndingStatement = buildNullExpression();
        }
        return unknownEndingStatement;
    }

    /**
     * Determines whether a query was parsed. The query may be incomplete but it started with one of
     * the three clauses (<b>SELECT</b>, <b>DELETE FROM</b>, or <b>UPDATE</b>).
     *
     * @return <code>true</code> the query was parsed; <code>false</code> otherwise
     */
    public boolean hasQueryStatement() {
        return queryStatement != null &&
              !queryStatement.isNull();
    }

    /**
     * Determines whether the query that got parsed had some malformed or unknown information.
     *
     * @return <code>true</code> if the query could not be parsed correctly
     * because it is either incomplete or malformed
     */
    public boolean hasUnknownEndingStatement() {
        return unknownEndingStatement != null &&
              !unknownEndingStatement.isNull();
    }

    @Override
    protected boolean isTolerant() {
        return tolerant;
    }

    @Override
    protected void parse(WordParser wordParser, boolean tolerant) {

        // Skip leading whitespace
        wordParser.skipLeadingWhitespace();

        // Parse the query, which can be invalid/incomplete or complete and valid
        // Make sure to use this statement if it's a JPQL fragment as well
        if (tolerant || (queryBNFId != JPQLStatementBNF.ID)) {

            // If the query BNF is not the "root" BNF, then we need to parse
            // it with a broader check when parsing
            if (queryBNFId == JPQLStatementBNF.ID) {
                queryStatement = parseUsingExpressionFactory(wordParser, queryBNFId, tolerant);
            }
            else {
                queryStatement = parse(wordParser, queryBNFId, tolerant);
            }

            int count = wordParser.skipLeadingWhitespace();

            // The JPQL query is invalid or incomplete, the remaining will be added
            // to the unknown ending statement
            if ((queryStatement == null) || !wordParser.isTail()) {
                wordParser.moveBackward(count);
                unknownEndingStatement = buildUnknownExpression(wordParser.substring());
            }
            // The JPQL query has some ending whitespace, keep one (used by content assist)
            else if (!wordParser.isTail() || (tolerant && (count > 0))) {
                unknownEndingStatement = buildUnknownExpression(" ");
            }
            // The JPQL query or fragment is invalid
            else if (queryStatement.isUnknown()) {
                unknownEndingStatement = buildUnknownExpression(queryStatement.toParsedText());
                queryStatement = null;
            }
        }
        // Quickly parse the valid query
        else {

            switch (wordParser.character()) {
                case 'd': case 'D': queryStatement = new DeleteStatement(this); break;
                case 'u': case 'U': queryStatement = new UpdateStatement(this); break;
                case 's': case 'S': queryStatement = new SelectStatement(this); break;
            }

            if (queryStatement != null) {
                queryStatement.parse(wordParser, tolerant);
            }
            else {
                queryStatement = parse(wordParser, queryBNFId, tolerant);
            }
        }
    }

    @Override
    protected void toParsedText(StringBuilder writer, boolean actual) {

        if (queryStatement != null) {
            queryStatement.toParsedText(writer, actual);
        }

        if (unknownEndingStatement != null) {
            unknownEndingStatement.toParsedText(writer, actual);
        }
    }
}
