/*
 * Copyright (c) 2012, 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.List;
import org.eclipse.persistence.jpa.jpql.ExpressionTools;
import org.eclipse.persistence.jpa.jpql.WordParser;
import org.eclipse.persistence.jpa.jpql.parser.FunctionExpressionFactory.ParameterCount;

/**
 * This expression adds support to call native database functions.
 * <p>
 * New to JPA 2.1.
 *
 * <div><b>BNF:</b> <code>func_expression ::= &lt;identifier&gt;('function_name' {, func_item}*)</code></div>
 *
 * @version 2.5
 * @since 2.4
 * @author James
 */
public final class FunctionExpression extends AbstractSingleEncapsulatedExpression {

    /**
     * The name of the SQL function.
     */
    private String functionName;

    /**
     * Determines whether the comma separating the function name and the first expression.
     */
    private boolean hasComma;

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

    /**
     * The number of {@link ParameterCount parameters} a {@link FunctionExpression} can have.
     *
     * @since 2.4
     */
    private ParameterCount parameterCount;

    /**
     * The unique identifier of the {@link JPQLQueryBNF} that will be used to parse the arguments of
     * the function expression.
     *
     * @since 2.4
     */
    private String parameterQueryBNFId;

    /**
     * Creates a new <code>FuncExpression</code>.
     *
     * @param parent The parent of this expression
     * @param identifier The JPQL identifier
     */
    public FunctionExpression(AbstractExpression parent, String identifier) {
        super(parent, identifier);
    }

    /**
     * Creates a new <code>FunctionExpression</code>.
     *
     * @param parent The parent of this expression
     * @param identifier The JPQL identifier
     * @param parameterCount The number of {@link ParameterCount parameters} a {@link
     * FunctionExpression} can have
     * @param parameterQueryBNFId The unique identifier of the {@link JPQLQueryBNF} that will be used
     * to parse the arguments of the function expression
     */
    public FunctionExpression(AbstractExpression parent,
                              String identifier,
                              ParameterCount parameterCount,
                              String parameterQueryBNFId) {

        this(parent, identifier);
        this.parameterCount      = parameterCount;
        this.parameterQueryBNFId = parameterQueryBNFId;
    }

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

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

        children.add(buildStringExpression(functionName));

        if (hasComma) {
            children.add(buildStringExpression(COMMA));
        }

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

        super.addOrderedEncapsulatedExpressionTo(children);
    }

    @Override
    public String getEncapsulatedExpressionQueryBNFId() {
        return parameterQueryBNFId;
    }

    /**
     * Returns the name of the SQL function.
     *
     * @return The name of the SQL function
     */
    public String getFunctionName() {
        return functionName;
    }

    /**
     * Returns the number of parameters a {@link FunctionExpression} can have, which will be during
     * validation.
     *
     * @return The number of parameters (encapsulated expressions) allowed by this expression
     * @since 2.4
     */
    public ParameterCount getParameterCount() {
        return parameterCount;
    }

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

    /**
     * Returns the name of the SQL function.
     *
     * @return The name of the SQL function
     */
    public String getUnquotedFunctionName() {
        return ExpressionTools.unquote(functionName);
    }

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

    @Override
    public boolean hasEncapsulatedExpression() {
        return hasFunctionName() || hasComma || super.hasEncapsulatedExpression();
    }

    /**
     * Determines whether the function name was parsed.
     *
     * @return <code>true</code> if the function name was parsed; <code>false</code> otherwise
     */
    public boolean hasFunctionName() {
        return ExpressionTools.stringIsNotEmpty(functionName);
    }

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

    @Override
    protected void parseEncapsulatedExpression(WordParser wordParser,
                                               int whitespaceCount,
                                               boolean tolerant) {

        int count = 0;

        // Parse the function name outside of a CollectionExpression so we can retrieve it
        // with getFunctionName()
        if (wordParser.startsWith(SINGLE_QUOTE)) {
            functionName = wordParser.word();
            wordParser.moveForward(functionName);
            count = wordParser.skipLeadingWhitespace();
        }
        else {
            functionName = ExpressionTools.EMPTY_STRING;
        }

        hasComma = wordParser.startsWith(COMMA);

        if (hasComma) {
            wordParser.moveForward(1);
            count = wordParser.skipLeadingWhitespace();
            hasSpaceAfterComma = count > 0;
        }

        // Parse the arguments
        if (!wordParser.isTail() &&
             wordParser.character() != RIGHT_PARENTHESIS) {

            super.parseEncapsulatedExpression(wordParser, whitespaceCount, tolerant);
        }

        // A space was parsed but no expression, let the space belong to the parent
        if (count > 0           &&
           !hasExpression()     &&
           !wordParser.isTail() &&
            wordParser.character() != RIGHT_PARENTHESIS) {

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

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

        writer.append(functionName);

        if (hasComma) {
            writer.append(COMMA);
        }

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

        super.toParsedTextEncapsulatedExpression(writer, actual);
    }
}
