/*
 * 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.ArrayList;
import java.util.Collection;
import java.util.List;
import org.eclipse.persistence.jpa.jpql.WordParser;

/**
 * This {@link Expression} takes care of parsing an expression that encapsulates three expressions
 * separated by a comma.
 *
 * <div><b>BNF:</b> <code>expression ::= &lt;identifier&gt;(first_expression, second_expression, third_expression)</code></div>
 *
 * @see LocateExpression
 * @see SubstringExpression
 *
 * @version 2.5.1
 * @since 2.3
 * @author Pascal Filion
 */
public abstract class AbstractTripleEncapsulatedExpression extends AbstractEncapsulatedExpression {

    /**
     * The {@link Expression} that represents the first expression.
     */
    private AbstractExpression firstExpression;

    /**
     * Determines whether the comma separating the first and second expression was parsed.
     */
    private boolean hasFirstComma;

    /**
     * Determines whether the comma separating the first and second expression was parsed.
     */
    private boolean hasSecondComma;

    /**
     * Determines whether a whitespace is following the comma.
     */
    private boolean hasSpaceAfterFirstComma;

    /**
     * Determines whether a whitespace is following the comma.
     */
    private boolean hasSpaceAfterSecondComma;

    /**
     * Determines which child expression is been currently parsed.
     */
    protected int parameterIndex;

    /**
     * The {@link Expression} that represents the second expression.
     */
    private AbstractExpression secondExpression;

    /**
     * The {@link Expression} that represents the first expression.
     */
    private AbstractExpression thirdExpression;

    /**
     * Creates a new <code>AbstractTripleEncapsulatedExpression</code>.
     *
     * @param parent The parent of this expression
     * @param identifier The JPQL identifier that starts this expression
     */
    protected AbstractTripleEncapsulatedExpression(AbstractExpression parent, String identifier) {
        super(parent, identifier);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void acceptChildren(ExpressionVisitor visitor) {
        getFirstExpression().accept(visitor);
        getSecondExpression().accept(visitor);
        getThirdExpression().accept(visitor);
    }

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

    /**
     * {@inheritDoc}
     */
    @Override
    protected void addOrderedEncapsulatedExpressionTo(List<Expression> children) {

        // Fist expression
        if (firstExpression != null) {
            children.add(firstExpression);
        }

        // ','
        if (hasFirstComma) {
            children.add(buildStringExpression(COMMA));
        }

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

        // Second expression
        if (secondExpression != null) {
            children.add(secondExpression);
        }

        // ','
        if (hasSecondComma) {
            children.add(buildStringExpression(COMMA));
        }

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

        // Third expression
        if (thirdExpression != null) {
            children.add(thirdExpression);
        }
    }

    /**
     * Creates a new {@link CollectionExpression} that will wrap the first, second and third
     * expressions.
     *
     * @return The first, second and third expressions represented by a temporary collection
     */
    public final CollectionExpression buildCollectionExpression() {

        List<AbstractExpression> children = new ArrayList<AbstractExpression>(3);
        children.add((AbstractExpression) getFirstExpression());
        children.add((AbstractExpression) getSecondExpression());
        children.add((AbstractExpression) getThirdExpression());

        List<Boolean> commas = new ArrayList<Boolean>(3);
        commas.add(hasFirstComma);
        commas.add(hasSecondComma);
        commas.add(Boolean.FALSE);

        List<Boolean> spaces = new ArrayList<Boolean>(3);
        spaces.add(hasSpaceAfterFirstComma);
        spaces.add(hasSpaceAfterSecondComma);
        spaces.add(Boolean.FALSE);

        return new CollectionExpression(this, children, commas, spaces, true);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public JPQLQueryBNF findQueryBNF(Expression expression) {

        if ((firstExpression != null) && firstExpression.isAncestor(expression)) {
            return getQueryBNF(getParameterQueryBNFId(0));
        }

        if ((secondExpression != null) && secondExpression.isAncestor(expression)) {
            return getQueryBNF(getParameterQueryBNFId(1));
        }

        if ((thirdExpression != null) && thirdExpression.isAncestor(expression)) {
            return getQueryBNF(getParameterQueryBNFId(2));
        }

        return super.findQueryBNF(expression);
    }

    /**
     * Returns the {@link Expression} that represents the first expression.
     *
     * @return The expression that was parsed representing the first expression
     */
    public final Expression getFirstExpression() {
        if (firstExpression == null) {
            firstExpression = buildNullExpression();
        }
        return firstExpression;
    }

    /**
     * Returns the unique identifier of the {@link JPQLQueryBNF} to be used to parse one of the
     * encapsulated expression at the given position.
     *
     * @param index The position of the encapsulated {@link Expression} that needs to be parsed
     * within the parenthesis, which starts at position 0
     * @return The ID of the {@link JPQLQueryBNF} to be used to parse one of the encapsulated expression
     */
    public abstract String getParameterQueryBNFId(int index);

    /**
     * Returns the {@link Expression} that represents the second expression.
     *
     * @return The expression that was parsed representing the second expression
     */
    public final Expression getSecondExpression() {
        if (secondExpression == null) {
            secondExpression = buildNullExpression();
        }
        return secondExpression;
    }

    /**
     * Returns the {@link Expression} that represents the first expression.
     *
     * @return The expression that was parsed representing the first expression
     */
    public final Expression getThirdExpression() {
        if (thirdExpression == null) {
            thirdExpression = buildNullExpression();
        }
        return thirdExpression;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean hasEncapsulatedExpression() {
        return hasFirstExpression()  || hasFirstComma  ||
               hasSecondExpression() || hasSecondComma ||
               hasThirdExpression();
    }

    /**
     * Determines whether the comma was parsed after the first expression.
     *
     * @return <code>true</code> if a comma was parsed after the first expression;
     * <code>false</code> otherwise
     */
    public final boolean hasFirstComma() {
        return hasFirstComma;
    }

    /**
     * Determines whether the first expression of the query was parsed.
     *
     * @return <code>true</code> if the first expression was parsed; <code>false</code> if it was not
     * parsed
     */
    public final boolean hasFirstExpression() {
        return firstExpression != null &&
              !firstExpression.isNull();
    }

    /**
     * Determines whether the comma was parsed after the second expression.
     *
     * @return <code>true</code> if a comma was parsed after the second expression; <code>false</code>
     * otherwise
     */
    public final boolean hasSecondComma() {
        return hasSecondComma;
    }

    /**
     * Determines whether the second expression of the query was parsed.
     *
     * @return <code>true</code> if the second expression was parsed; <code>false</code> if it was
     * not parsed
     */
    public final boolean hasSecondExpression() {
        return secondExpression != null &&
              !secondExpression.isNull();
    }

    /**
     * Determines whether a whitespace was parsed after the first comma.
     *
     * @return <code>true</code> if there was a whitespace after the first comma; <code>false</code>
     * otherwise
     */
    public final boolean hasSpaceAfterFirstComma() {
        return hasSpaceAfterFirstComma;
    }

    /**
     * Determines whether a whitespace was parsed after the second comma.
     *
     * @return <code>true</code> if there was a whitespace after the second comma; <code>false</code>
     * otherwise
     */
    public final boolean hasSpaceAfterSecondComma() {
        return hasSpaceAfterSecondComma;
    }

    /**
     * Determines whether the third expression of the query was parsed.
     *
     * @return <code>true</code> if the third expression was parsed; <code>false</code> if it was not
     * parsed
     */
    public final boolean hasThirdExpression() {
        return thirdExpression != null &&
              !thirdExpression.isNull();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected boolean isParsingComplete(WordParser wordParser, String word, Expression expression) {

        char character = wordParser.character();

        // When parsing an invalid JPQL query (eg: LOCATE + ABS(e.name)) then "+ ABS(e.name)"
        // should not be parsed as an invalid first expression
        if ((parameterIndex == 0) &&
            ((character == '+') || (character == '-')) &&
            !hasLeftParenthesis()) {

            parameterIndex = -1;
            return true;
        }

        return super.isParsingComplete(wordParser, word, expression);
    }

    /**
     * Determines whether the third expression is an optional expression, which means a valid query
     * can have it or not.
     *
     * @return <code>true</code> if the third expression can either be present or not in a valid
     * query; <code>false</code> if it's mandatory
     */
    protected abstract boolean isThirdExpressionOptional();

    /**
     * {@inheritDoc}
     */
    @Override
    protected void parseEncapsulatedExpression(WordParser wordParser,
                                               int whitespaceCount,
                                               boolean tolerant) {

        int count = 0;

        // Parse the first expression
        parameterIndex = 0;
        firstExpression = parse(wordParser, getParameterQueryBNFId(0), tolerant);

        if (firstExpression != null) {
            count = wordParser.skipLeadingWhitespace();
        }
        // See comment in isParsingComplete()
        else if (parameterIndex == -1) {
            return;
        }

        // Parse ','
        hasFirstComma = wordParser.startsWith(COMMA);

        if (hasFirstComma) {
            count = 0;
            wordParser.moveForward(1);
            hasSpaceAfterFirstComma = wordParser.skipLeadingWhitespace() > 0;
        }

        // Parse the second expression
        parameterIndex = 1;
        secondExpression = parse(wordParser, getParameterQueryBNFId(1), tolerant);

        if (!hasFirstComma) {
            hasSpaceAfterFirstComma = (count > 0);
        }

        count = wordParser.skipLeadingWhitespace();

        // Parse ','
        hasSecondComma = wordParser.startsWith(COMMA);

        if (hasSecondComma) {
            count = 0;
            wordParser.moveForward(1);
            hasSpaceAfterSecondComma = wordParser.skipLeadingWhitespace() > 0;
        }

        // Parse the third expression
        parameterIndex = 2;
        thirdExpression = parse(wordParser, getParameterQueryBNFId(2), tolerant);

        if (!hasSecondComma && (!isThirdExpressionOptional() || (thirdExpression != null))) {
            hasSpaceAfterSecondComma = (count > 0);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void removeEncapsulatedExpression() {
        hasFirstComma = false;
        hasSecondComma = false;
        firstExpression = null;
        thirdExpression = null;
        secondExpression = null;
        hasSpaceAfterFirstComma = false;
        hasSpaceAfterSecondComma = false;
    }

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

        // First expression
        if (firstExpression != null) {
            firstExpression.toParsedText(writer, actual);
        }

        // ','
        if (hasFirstComma) {
            writer.append(COMMA);
        }

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

        // Second expression
        if (secondExpression != null) {
            secondExpression.toParsedText(writer, actual);
        }

        // ','
        if (hasSecondComma) {
            writer.append(COMMA);
        }

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

        // Third expression
        if (thirdExpression != null) {
            thirdExpression.toParsedText(writer, actual);
        }
    }
}
