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

/**
 * The state field path expression must have a string, numeric, or enum value. The literal and/or
 * input parameter values must be like the same abstract schema type of the state field path
 * expression in type.
 * <p>
 * The results of the subquery must be like the same abstract schema type of the state field path
 * expression in type.
 * <p>
 * There must be at least one element in the comma separated list that defines the set of values for
 * the <b>IN</b> expression. If the value of a state field path expression in an <b>IN</b> or
 * <b>NOT IN</b> expression is <b>NULL</b> or unknown, the value of the expression is unknown.
 * <p>
 * JPA 1.0:
 * <div><b>BNF:</b> <code>in_expression ::= state_field_path_expression [NOT] IN(in_item {, in_item}* | subquery)</code></div>
 * <br>
 * JPA 2.0:
 * <div><b>BNF:</b> <code>in_expression ::= {state_field_path_expression | type_discriminator} [NOT] IN { ( in_item {, in_item}* ) | (subquery) | collection_valued_input_parameter }</code></div>
 * <p>
 * EclipseLink 2.1:
 * <div><b>BNF:</b> <code>in_item ::= literal | single_valued_input_parameter | scalar_expression</code></div>
 * <p>
 * EclipseLink 2.5:
 * <div><b>BNF:</b> <pre><code> in_expression ::= { in_expression_expression | nested_array_expression } [NOT] IN { ( in_item {, in_item}* ) | (subquery) | ( nested_array_item {, nested_array_item}+ ) | collection_valued_input_parameter }
 *
 * in_expression_expression ::= { state_field_path_expression | type_discriminator |
 *                                single_valued_input_parameter | identification_variable |
 *                                scalar_expression }
 *
 * nested_array_expression ::= ( in_expression_expression {, in_expression_expression}+ )
 *
 * nested_array_item ::= ( in_item {, in_item}+ )</code></pre></div>
 *
 * <div>Example: <code><b>SELECT</b> c <b>FROM</b> Customer c <b>WHERE</b> c.home.city <b>IN</b> :city</code></div>
 *
 * <div>Example: <code><b>SELECT</b> p <b>FROM</b> Project p <b>WHERE</b> <b>TYPE</b>(p) <b>IN</b>(LargeProject, SmallProject)</code></div>
 *
 * @version 2.5.1
 * @since 2.3
 * @author Pascal Filion
 */
public final class InExpression extends AbstractExpression {

    /**
     * The expression before the 'IN' identifier used for identification.
     */
    private AbstractExpression expression;

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

    /**
     * Flag used to determine if a space was parsed after <code>IN</code> if the left parenthesis was
     * not parsed.
     */
    private boolean hasSpaceAfterIn;

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

    /**
     * The expression within parenthesis, which can be one or many expressions.
     */
    private AbstractExpression inItems;

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

    /**
     * Determines whether what was parsed after the <code>IN</code> identifier is a single input parameter.
     */
    private Boolean singleInputParameter;

    /**
     * Creates a new <code>InExpression</code>.
     *
     * @param parent The parent of this expression
     * @param expression The state field path expression that was parsed prior of parsing this
     * expression
     */
    public InExpression(AbstractExpression parent, AbstractExpression expression) {
        super(parent, IN);

        if (expression != null) {
            this.expression = expression;
            this.expression.setParent(this);
        }
    }

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

    @Override
    public void acceptChildren(ExpressionVisitor visitor) {
        getExpression().accept(visitor);
        getInItems().accept(visitor);
    }

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

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

        // State field path expression or type discriminator
        if (hasExpression()) {
            children.add(expression);
            children.add(buildStringExpression(SPACE));
        }

        // 'NOT'
        if (notIdentifier != null) {
            children.add(buildStringExpression(NOT));
            children.add(buildStringExpression(SPACE));
        }

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

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

        // In items
        if (hasInItems()) {
            children.add(inItems);
        }

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

    @Override
    public JPQLQueryBNF findQueryBNF(Expression expression) {

        if (this.expression.isAncestor(expression)) {
            return getQueryBNF(InExpressionExpressionBNF.ID);
        }

        if (inItems.isAncestor(expression)) {
            return getQueryBNF(InExpressionItemBNF.ID);
        }

        return super.findQueryBNF(expression);
    }

    /**
     * Returns the actual <b>IN</b> 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 actual <b>NOT</b> found in the string representation of the JPQL query, which has
     * the actual case that was used.
     *
     * @return The <b>NOT</b> identifier that was actually parsed, or an empty string if it was not parsed
     */
    public String getActualNotIdentifier() {
        return (notIdentifier != null) ? notIdentifier : ExpressionTools.EMPTY_STRING;
    }

    /**
     * Returns the {@link Expression} that represents the state field path expression or type
     * discriminator.
     *
     * @return The expression that was parsed representing the state field path expression or the
     * type discriminator
     */
    public Expression getExpression() {
        if (expression == null) {
            expression = buildNullExpression();
        }
        return expression;
    }

    /**
     * Returns the unique identifier of the query BNF that describes the expression being tested by
     * the <code>IN</code> expression.
     *
     * @return {@link InExpressionExpressionBNF#ID}
     */
    public String getExpressionExpressionQueryBNFId() {
        return InExpressionExpressionBNF.ID;
    }

    /**
     * Returns the unique identifier of the query BNF that describes the items being tested against.
     *
     * @return {@link InExpressionItemBNF#ID}
     */
    public String getExpressionItemQueryBNFId() {
        return InExpressionItemBNF.ID;
    }

    /**
     * Returns the identifier for this expression.
     *
     * @return Either <b>IS IN</b> or <b>IN</b>
     */
    public String getIdentifier() {
        return (notIdentifier != null) ? NOT_IN : IN;
    }

    /**
     * Returns the {@link Expression} that represents the list if items.
     *
     * @return The expression that was parsed representing the list of items
     */
    public Expression getInItems() {
        if (inItems == null) {
            inItems = buildNullExpression();
        }
        return inItems;
    }

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

    /**
     * Determines whether the state field path expression or type discriminator was parsed.
     *
     * @return <code>true</code> if the state field path expression or type discriminator was parsed;
     * <code>false</code> if it was not parsed
     */
    public boolean hasExpression() {
        return expression != null &&
              !expression.isNull();
    }

    /**
     * Determines whether the list of items was parsed.
     *
     * @return <code>true</code> if at least one item was parsed; <code>false</code> otherwise
     */
    public boolean hasInItems() {
        return inItems != null &&
              !inItems.isNull();
    }

    /**
     * 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 identifier <b>NOT</b> was parsed.
     *
     * @return <code>true</code> if the identifier <b>NOT</b> was parsed; <code>false</code> otherwise
     */
    public boolean hasNot() {
        return notIdentifier != null;
    }

    /**
     * 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 there was a whitespace after the <code>IN</code> identifier if the left
     * parenthesis was not parsed.
     *
     * @return <code>true</code> if a whitespace was parsed after <code>IN</code> in the string
     * version of the query; <code>false</code> otherwise
     * @since 2.4
     */
    public boolean hasSpaceAfterIn() {
        return hasSpaceAfterIn;
    }

    @Override
    protected boolean isParsingComplete(WordParser wordParser, String word, Expression expression) {
        return word.equalsIgnoreCase(AND) ||
               word.equalsIgnoreCase(OR)  ||
               super.isParsingComplete(wordParser, word, expression);
    }

    /**
     * Determines whether what was parsed after the <code>IN</code> identifier is a single input
     * parameter:
     * <div><b>BNF:</b> <code>in_expression ::= {state_field_path_expression | type_discriminator} [NOT] IN collection_valued_input_parameter</code></div>
     *
     * @return <code>true</code> if what is following the <code>IN</code> identifier is a single
     * input parameter (without the left or right parenthesis); <code>false</code> otherwise
     * @since 2.4
     */
    public boolean isSingleInputParameter() {

        if (singleInputParameter == null) {

            if (hasLeftParenthesis || hasRightParenthesis)  {
                singleInputParameter = Boolean.FALSE;
            }
            else {
                WordParser wordParser = new WordParser(getInItems().toActualText());
                String word = wordParser.word();
                wordParser.moveForward(word);

                singleInputParameter = (word.length() > 0) &&
                                       ExpressionTools.isParameter(word.charAt(0)) &&
                                       wordParser.isTail();
            }
        }

        return singleInputParameter;
    }

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

        // Parse 'NOT'
        if (wordParser.startsWithIgnoreCase('N')) {
            notIdentifier = wordParser.moveForward(NOT);
            wordParser.skipLeadingWhitespace();
        }

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

        int count = wordParser.skipLeadingWhitespace();
        hasSpaceAfterIn = (count > 0);

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

        if (hasLeftParenthesis) {
            wordParser.moveForward(1);
            count = wordParser.skipLeadingWhitespace();
        }

        // Parse the items
        inItems = parse(wordParser, InExpressionItemBNF.ID, tolerant);

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

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

        if (hasRightParenthesis) {

            // Temporarily change the state so isSingleInputParameter() return the right info
            hasRightParenthesis = false;

            // If it's a single input parameter that is not encapsulated by parenthesis, then
            // we'll ignore the right parenthesis, it could be part of an encapsulated subquery,
            // example: ... WHERE (SELECT e FROM Employee e WHERE e.name IN :input_1) = :input_2
            if (hasLeftParenthesis || !isSingleInputParameter()) {
                hasRightParenthesis = true;
                wordParser.moveForward(1);
            }
        }
    }

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

        // State field path expression or type discriminator
        if (hasExpression()) {
            expression.toParsedText(writer, actual);
            writer.append(SPACE);
        }

        // 'NOT'
        if (notIdentifier != null) {
            writer.append(actual ? notIdentifier : NOT);
            writer.append(SPACE);
        }

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

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

        // IN items
        if (hasInItems()) {
            inItems.toParsedText(writer, actual);
        }

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