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

/**
 * An identification variable declared by a collection member declaration ranges over values of a
 * collection obtained by navigation using a path expression. Such a path expression represents a
 * navigation involving the association-fields of an entity abstract schema type. Because a path
 * expression can be based on another path expression, the navigation can use the association-fields
 * of related entities. An identification variable of a collection member declaration is declared
 * using a special operator, the reserved identifier <b>IN</b>. The argument to the <b>IN</b>
 * operator is a collection-valued path expression. The path expression evaluates to a collection
 * type specified as a result of navigation to a collection-valued association-field of an entity
 * abstract schema type.
 *
 * <div><b>BNF:</b> <code>collection_member_declaration ::= IN(collection_valued_path_expression) [AS] identification_variable</code><p></p></div>
 * or
 * <div><b>BNF:</b> <code>derived_collection_member_declaration ::= IN superquery_identification_variable.{single_valued_object_field.}*collection_valued_field</code><p></p></div>
 * <p>
 * Example: <code><b>SELECT</b> t <b>FROM</b> Player p, <b>IN</b> (p.teams) AS t</code>
 *
 * @version 2.5
 * @since 2.3
 * @author Pascal Filion
 */
public final class CollectionMemberDeclaration extends AbstractExpression {

    /**
     * The actual <b>AS</b> identifier found in the string representation of the JPQL query.
     */
    private String asIdentifier;

    /**
     * The {@link Expression} representing the collection member, which is declared by an
     * identification variable.
     */
    private AbstractExpression collectionValuedPathExpression;

    /**
     * Flag used to determine if the closing parenthesis is present in the query.
     */
    private boolean hasLeftParenthesis;

    /**
     * Flag used to determine if the opening parenthesis is present in the query.
     */
    private boolean hasRightParenthesis;

    /**
     * Determines whether a whitespace was parsed after <b>AS</b>.
     */
    private boolean hasSpaceAfterAs;

    /**
     * Determines whether a whitespace was parsed after <b>IN</b>.
     */
    private boolean hasSpaceAfterIn;

    /**
     * Determines whether a whitespace was parsed after the right parenthesis.
     */
    private boolean hasSpaceAfterRightParenthesis;

    /**
     * The {@link Expression} representing the identification variable, which maps the collection-
     * valued path expression.
     */
    private AbstractExpression identificationVariable;

    /**
     * The actual <b>IN</b> identifier found in the string representation of the JPQL query.
     */
    private String inIdentifier;

    /**
     * Creates a new <code>CollectionMemberDeclaration</code>.
     *
     * @param parent The parent of this expression
     */
    public CollectionMemberDeclaration(AbstractExpression parent) {
        super(parent, IN);
    }

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

    @Override
    public void acceptChildren(ExpressionVisitor visitor) {
        getCollectionValuedPathExpression().accept(visitor);
        getIdentificationVariable().accept(visitor);
    }

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

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

        // 'IN'
        children.add(buildStringExpression(IN));

        if (hasSpaceAfterIn) {
            children.add(buildStringExpression(SPACE));
        }

        // '('
        if (hasLeftParenthesis) {
            children.add(buildStringExpression(LEFT_PARENTHESIS));
        }

        // Collection-valued path expression
        if (collectionValuedPathExpression != null) {
            children.add(collectionValuedPathExpression);
        }

        // ')'
        if (hasRightParenthesis) {
            children.add(buildStringExpression(RIGHT_PARENTHESIS));
        }

        if (hasSpaceAfterRightParenthesis) {
            children.add(buildStringExpression(SPACE));
        }

        // AS
        if (asIdentifier != null) {
            children.add(buildStringExpression(AS));
        }

        if (hasSpaceAfterAs) {
            children.add(buildStringExpression(SPACE));
        }

        // Identification variable
        if (identificationVariable != null) {
            children.add(identificationVariable);
        }
    }

    @Override
    public JPQLQueryBNF findQueryBNF(Expression expression) {

        if ((collectionValuedPathExpression != null) && collectionValuedPathExpression.isAncestor(expression)) {
            return getQueryBNF(CollectionValuedPathExpressionBNF.ID);
        }

        if ((identificationVariable != null) && identificationVariable.isAncestor(expression)) {
            return getQueryBNF(IdentificationVariableBNF.ID);
        }

        return super.findQueryBNF(expression);
    }

    /**
     * Returns the actual <b>AS</b> identifier found in the string representation of the JPQL query,
     * which has the actual case that was used.
     *
     * @return The <b>AS</b> identifier that was actually parsed
     */
    public String getActualAsIdentifier() {
        return asIdentifier;
    }

    /**
     * Returns the actual <b>IN</b> identifier found in the string representation of the JPQL query,
     * which has the actual case that was used.
     *
     * @return The <b>IN</b> identifier that was actually parsed
     */
    public String getActualInIdentifier() {
        return inIdentifier;
    }

    /**
     * Returns the {@link Expression} representing the collection member, which is declared by an
     * identification variable.
     *
     * @return The expression representing the collection-valued path expression
     */
    public Expression getCollectionValuedPathExpression() {
        if (collectionValuedPathExpression == null) {
            collectionValuedPathExpression = buildNullExpression();
        }
        return collectionValuedPathExpression;
    }

    /**
     * Returns the {@link Expression} representing the identification variable, which maps the
     * collection-valued path expression.
     *
     * @return The expression representing the identification variable
     */
    public Expression getIdentificationVariable() {
        if (identificationVariable == null) {
            identificationVariable = buildNullExpression();
        }
        return identificationVariable;
    }

    @Override
    public JPQLQueryBNF getQueryBNF() {
        return getQueryBNF(CollectionMemberDeclarationBNF.ID);
    }

    /**
     * Determines whether the identifier <b>AS</b> was parsed.
     *
     * @return <code>true</code> if the identifier <b>AS</b> was parsed; <code>false</code> otherwise
     */
    public boolean hasAs() {
        return asIdentifier != null;
    }

    /**
     * Determines whether the collection-valued path expression was parsed.
     *
     * @return <code>true</code> if the query has the collection-valued path expression;
     * <code>false</code> otherwise
     */
    public boolean hasCollectionValuedPathExpression() {
        return collectionValuedPathExpression != null &&
              !collectionValuedPathExpression.isNull();
    }

    /**
     * Determines whether the identification variable was parsed.
     *
     * @return <code>true</code> if the query has the identification variable; <code>false</code>
     * otherwise
     */
    public boolean hasIdentificationVariable() {
        return identificationVariable != null  &&
              !identificationVariable.isNull() &&
              !identificationVariable.isVirtual();
    }

    /**
     * Determines whether the open parenthesis was parsed or not.
     *
     * @return <code>true</code> if the open parenthesis was present in the string version of the
     * query; <code>false</code> otherwise
     */
    public boolean hasLeftParenthesis() {
        return hasLeftParenthesis;
    }

    /**
     * Determines whether the close parenthesis was parsed or not.
     *
     * @return <code>true</code> if the close parenthesis was present in the string version of the
     * query; <code>false</code> otherwise
     */
    public boolean hasRightParenthesis() {
        return hasRightParenthesis;
    }

    /**
     * Determines whether a whitespace was found after <b>AS</b>.
     *
     * @return <code>true</code> if there was a whitespace after <b>AS</b>; <code>false</code>
     * otherwise
     */
    public boolean hasSpaceAfterAs() {
        return hasSpaceAfterAs;
    }

    /**
     * Determines whether a whitespace was found after <b>IN</b>.
     *
     * @return <code>true</code> if there was a whitespace after <b>IN</b>; <code>false</code>
     * otherwise
     */
    public boolean hasSpaceAfterIn() {
        return hasSpaceAfterIn;
    }

    /**
     * Determines whether a whitespace was found after the close parenthesis.
     *
     * @return <code>true</code> if there was a whitespace after the right parenthesis;
     * <code>false</code> otherwise
     */
    public boolean hasSpaceAfterRightParenthesis() {
        return hasSpaceAfterRightParenthesis;
    }

    /**
     * Determines whether this collection member declaration is used as a derived collection-valued
     * path expression.
     *
     * @return <code>true</code> if this collection member declaration is used as this form:
     * "<code><b>IN</b> collection_valued_path_expression</code>" in a subquery; <code>false</code>
     * if it's used as this form: <code><b>IN</b>(collection_valued_path_expression)
     * [<b>AS</b>] identification_variable</code>" in a top-level or subquery queries
     * @since 2.4
     */
    public boolean isDerived() {
        return !hasLeftParenthesis            &&
               !hasRightParenthesis           &&
               !hasSpaceAfterRightParenthesis &&
                asIdentifier == null          &&
               !hasIdentificationVariable();
    }

    @Override
    protected boolean isParsingComplete(WordParser wordParser, String word, Expression expression) {
        return wordParser.character() == RIGHT_PARENTHESIS ||
               word.equalsIgnoreCase(AS)                   ||
               super.isParsingComplete(wordParser, word, expression);
    }

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

        // Parse 'IN'
        inIdentifier = wordParser.moveForward(IN);

        int count = wordParser.skipLeadingWhitespace();

        // Parse '('
        hasLeftParenthesis = wordParser.startsWith(LEFT_PARENTHESIS);

        if (hasLeftParenthesis) {
            wordParser.moveForward(1);
            count = wordParser.skipLeadingWhitespace();
        }
        // For JPA 2.0 a derived collection member declaration
        else {
            hasSpaceAfterIn = (count > 0);
            count = 0;
        }

        // Parse the collection-valued path expression
        collectionValuedPathExpression = parse(
            wordParser,
            CollectionValuedPathExpressionBNF.ID,
            tolerant
        );

        if (collectionValuedPathExpression != null) {
            count = wordParser.skipLeadingWhitespace();
        }

        // Parse ')'
        hasRightParenthesis = wordParser.startsWith(RIGHT_PARENTHESIS);

        if (hasRightParenthesis) {
            wordParser.moveForward(1);
            count = wordParser.skipLeadingWhitespace();
            hasSpaceAfterRightParenthesis = count > 0;

            // Special case for derived collection-valued path expression
            if (!hasLeftParenthesis                  &&
                !wordParser.startsWithIdentifier(AS) &&
                (wordParser.isTail() || isParsingComplete(wordParser, wordParser.word(), null))) {

                hasRightParenthesis = false;
                hasSpaceAfterRightParenthesis = false;
                wordParser.moveBackward(count + 1);
                return;
            }
        }
        else {
            hasSpaceAfterRightParenthesis = (count > 0);
        }

        // Parse 'AS'
        if (wordParser.startsWithIdentifier(AS)) {
            asIdentifier = wordParser.moveForward(AS);
            hasSpaceAfterAs = wordParser.skipLeadingWhitespace() > 0;
        }

        // Parse the identification variable
        boolean parseVariable = true;

        if (!tolerant                      &&
            !hasLeftParenthesis            &&
            !hasRightParenthesis           &&
             hasSpaceAfterRightParenthesis &&
             asIdentifier == null          &&
             isParsingComplete(wordParser, wordParser.word(), null)) {

            parseVariable = false;
        }

        if (parseVariable) {
            identificationVariable = parse(wordParser, IdentificationVariableBNF.ID, tolerant);
        }

        // Revert back some options because what was parsed is a derived collection member declaration
        if (!hasLeftParenthesis            &&
            !hasRightParenthesis           &&
             hasSpaceAfterRightParenthesis &&
             asIdentifier == null          &&
             identificationVariable == null) {

            hasSpaceAfterRightParenthesis = false;
            wordParser.moveBackward(count);
        }
    }

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

        // 'IN'
        writer.append(actual ? inIdentifier : getText());

        // '('
        if (hasLeftParenthesis) {
            writer.append(LEFT_PARENTHESIS);
        }
        else if (hasSpaceAfterIn) {
            writer.append(SPACE);
        }

        // Collection-valued path expression
        if (collectionValuedPathExpression != null) {
            collectionValuedPathExpression.toParsedText(writer, actual);
        }

        // ')'
        if (hasRightParenthesis) {
            writer.append(RIGHT_PARENTHESIS);
        }

        if (hasSpaceAfterRightParenthesis) {
            writer.append(SPACE);
        }

        // 'AS'
        if (asIdentifier != null) {
            writer.append(actual ? asIdentifier : AS);
        }

        if (hasSpaceAfterAs) {
            writer.append(SPACE);
        }

        // Identification variable
        if (identificationVariable != null) {
            identificationVariable.toParsedText(writer, actual);
        }
    }

    /**
     * Creates a string representation of this expression up and excluding the <b>AS</b> identifier.
     *
     * @return The string representation of a section of this expression
     */
    public String toParsedTextUntilAs() {

        StringBuilder writer = new StringBuilder();

        // 'IN'
        writer.append(getText());

        // '('
        if (hasLeftParenthesis) {
            writer.append(LEFT_PARENTHESIS);
        }
        else if (hasSpaceAfterIn) {
            writer.append(SPACE);
        }

        // Collection-valued path expression
        if (collectionValuedPathExpression != null) {
            collectionValuedPathExpression.toParsedText(writer, false);
        }

        // ')'
        if (hasRightParenthesis) {
            writer.append(RIGHT_PARENTHESIS);
        }

        if (hasSpaceAfterRightParenthesis) {
            writer.append(SPACE);
        }

        return writer.toString();
    }
}
