/*
 * 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.ExpressionTools;
import org.eclipse.persistence.jpa.jpql.WordParser;

/**
 * This is the update clause of the update statement.
 * <p>
 * An <b>UPDATE</b> statement provides bulk operations over sets of entities of a single entity
 * class (together with its subclasses, if any). Only one entity abstract schema type may be
 * specified in the <b>UPDATE</b> clause.
 *
 * <div><b>BNF:</b> <code>update_clause ::= UPDATE abstract_schema_name [[AS] identification_variable] SET update_item {, update_item}*</code></div>
 *
 * @see UpdateStatement
 * @see UpdateItem
 *
 * @version 2.5
 * @since 2.3
 * @author Pascal Filion
 */
public final class UpdateClause extends AbstractExpression {

    /**
     * Determines whether a whitespace was parsed after the abstract schema name declaration.
     */
    private boolean hasSpaceAfterRangeVariableDeclaration;

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

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

    /**
     * The {@link Expression} representing the range variable declaration.
     */
    private AbstractExpression rangeVariableDeclaration;

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

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

    /**
     * The expression containing the update items.
     */
    private AbstractExpression updateItems;

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

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

    @Override
    public void acceptChildren(ExpressionVisitor visitor) {
        getRangeVariableDeclaration().accept(visitor);
        getUpdateItems().accept(visitor);
    }

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

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

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

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

        // Range variable declaration
        if (rangeVariableDeclaration != null) {
            children.add(rangeVariableDeclaration);
        }

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

        // 'SET'
        if (setIdentifier != null) {
            children.add(buildStringExpression(SET));
        }

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

        // Update items
        if (updateItems != null) {
            children.add(updateItems);
        }
    }

    /**
     * Creates a new {@link CollectionExpression} that will wrap the single update item.
     *
     * @return The single update item represented by a temporary collection
     */
    public CollectionExpression buildCollectionExpression() {

        List<AbstractExpression> children = new ArrayList<>(1);
        children.add((AbstractExpression) getUpdateItems());

        List<Boolean> commas = new ArrayList<>(1);
        commas.add(Boolean.FALSE);

        List<Boolean> spaces = new ArrayList<>(1);
        spaces.add(Boolean.FALSE);

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

    @Override
    public JPQLQueryBNF findQueryBNF(Expression expression) {

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

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

        return super.findQueryBNF(expression);
    }

    /**
     * Returns the actual <b>SET</b> found in the string representation of the JPQL query, which has
     * the actual case that was used.
     *
     * @return The <b>SET</b> identifier that was actually parsed, or an empty string if it was not parsed
     */
    public String getActualSetIdentifier() {
        return (setIdentifier != null) ? setIdentifier : ExpressionTools.EMPTY_STRING;
    }

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

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

    /**
     * Returns the {@link Expression} representing the range variable declaration.
     *
     * @return The expression that was parsed representing the range variable declaration
     */
    public Expression getRangeVariableDeclaration() {
        if (rangeVariableDeclaration == null) {
            rangeVariableDeclaration = buildNullExpression();
        }
        return rangeVariableDeclaration;
    }

    /**
     * Returns the {@link Expression} representing the single update item or the collection of update items.
     *
     * @return The expression that was parsed representing the single or multiple update items
     */
    public Expression getUpdateItems() {
        if (updateItems == null) {
            updateItems = buildNullExpression();
        }
        return updateItems;
    }

    /**
     * Determines whether the range variable declaration was parsed.
     *
     * @return <code>true</code> if the range variable declaration was parsed; <code>false</code> otherwise
     */
    public boolean hasRangeVariableDeclaration() {
        return rangeVariableDeclaration != null &&
              !rangeVariableDeclaration.isNull();
    }

    /**
     * Determines whether <b>SET</b> was parsed or not.
     *
     * @return <code>true</code> if <b>SET</b> was part of the query; <code>false</code> otherwise
     */
    public boolean hasSet() {
        return setIdentifier != null;
    }

    /**
     * Determines whether a whitespace was found after the abstract schema name declaration.
     *
     * @return <code>true</code> if there was a whitespace after the abstract schema name declaration;
     * <code>false</code> otherwise
     */
    public boolean hasSpaceAfterRangeVariableDeclaration() {
        return hasSpaceAfterRangeVariableDeclaration;
    }

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

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

    /**
     * Determines whether the update items section of the query was parsed.
     *
     * @return <code>true</code> if something was parsed after <b>SET</b> even if it was a malformed
     * expression; <code>false</code> if nothing was parsed
     */
    public boolean hasUpdateItems() {
        return updateItems != null &&
              !updateItems.isNull();
    }

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

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

        // Parse 'UPDATE'
        updateIdentifier = wordParser.moveForward(UPDATE);

        hasSpaceAfterUpdate = wordParser.skipLeadingWhitespace() > 0;

        // Parse the abstract schema name
        if (tolerant && !wordParser.startsWithIdentifier(SET)) {
            rangeVariableDeclaration = parse(
                wordParser,
                RangeVariableDeclarationBNF.ID,
                tolerant
            );
        }
        else if (!tolerant) {
            rangeVariableDeclaration = new RangeVariableDeclaration(this);
            rangeVariableDeclaration.parse(wordParser, tolerant);
        }

        hasSpaceAfterRangeVariableDeclaration = wordParser.skipLeadingWhitespace() > 0;

        // Parse 'SET'
        if (!tolerant || wordParser.startsWithIdentifier(SET)) {
            setIdentifier = wordParser.moveForward(SET);
            hasSpaceAfterSet = wordParser.skipLeadingWhitespace() > 0;
        }

        // Parse update items
        updateItems = parse(wordParser, InternalUpdateClauseBNF.ID, tolerant);
    }

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

        // 'UPDATE'
        writer.append(actual ? updateIdentifier : UPDATE);

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

        // Range variable declaration
        if (rangeVariableDeclaration != null) {
            rangeVariableDeclaration.toParsedText(writer, actual);
        }

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

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

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

        // Update items
        if (updateItems != null) {
            updateItems.toParsedText(writer, actual);
        }
    }
}
