/*
 * Copyright (c) 2006, 2020 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;
    }

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

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

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

    /**
     * {@inheritDoc}
     */
    @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();
    }

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

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

    /**
     * {@inheritDoc}
     */
    @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();
    }

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

    /**
     * {@inheritDoc}
     */
    @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);
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void toParsedText(StringBuilder writer, boolean actual) {

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

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