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

/**
 * The <code>new_value</code> specified for an update operation must be compatible in type with the
 * field to which it is assigned.
 *
 * <div><b>BNF:</b> <code>update_item ::= [identification_variable.]{state_field | single_valued_association_field} = new_value</code></div>
 *
 * @see UpdateClause
 *
 * @version 2.5
 * @since 2.3
 * @author Pascal Filion
 */
public final class UpdateItem extends AbstractExpression {

    /**
     * Determines whether the equal sign was parsed or not.
     */
    private boolean hasEqualSign;

    /**
     * Determines whether a whitespace was parsed after the equal sign or not.
     */
    private boolean hasSpaceAfterEqualSign;

    /**
     * Determines whether a whitespace was parsed before the equal sign or not
     */
    private boolean hasSpaceAfterStateFieldPathExpression;

    /**
     * The expression representing the new value.
     */
    private AbstractExpression newValue;

    /**
     * The expression representing the state field to have its value updated.
     */
    private AbstractExpression stateFieldExpression;

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

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

    @Override
    public void acceptChildren(ExpressionVisitor visitor) {
        getStateFieldPathExpression().accept(visitor);
        getNewValue().accept(visitor);
    }

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

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

        // State field expression
        if (stateFieldExpression != null) {
            children.add(stateFieldExpression);
        }

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

        // '='
        if (hasEqualSign) {
            children.add(buildStringExpression(EQUAL));
        }

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

        // New value
        if (newValue != null) {
            children.add(newValue);
        }
    }

    @Override
    public JPQLQueryBNF findQueryBNF(Expression expression) {

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

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

        return super.findQueryBNF(expression);
    }

    /**
     * Returns the {@link Expression} representing the new value, which is the new value of the property.
     *
     * @return The expression for the new value
     */
    public Expression getNewValue() {
        if (newValue == null) {
            newValue = buildNullExpression();
        }
        return newValue;
    }

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

    /**
     * Returns the {@link Expression} representing the state field path expression, which is the
     * property that should get updated.
     *
     * @return The expression for the state field path expression
     */
    public Expression getStateFieldPathExpression() {
        if (stateFieldExpression == null) {
            stateFieldExpression = buildNullExpression();
        }
        return stateFieldExpression;
    }

    /**
     * Determines whether the equal sign was parsed or not.
     *
     * @return <code>true</code> if the equal sign was parsed; <code>false</code> otherwise
     */
    public boolean hasEqualSign() {
        return hasEqualSign;
    }

    /**
     * Determines whether the new value section of the query was parsed.
     *
     * @return <code>true</code> the new value was parsed; <code>false</code> if nothing was parsed
     */
    public boolean hasNewValue() {
        return newValue != null &&
              !newValue.isNull();
    }

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

    /**
     * Determines whether a whitespace was parsed after the state field path expression not.
     *
     * @return <code>true</code> if there was a whitespace after the state field path expression;
     * <code>false</code> otherwise
     */
    public boolean hasSpaceAfterStateFieldPathExpression() {
        return hasSpaceAfterStateFieldPathExpression;
    }

    /**
     * Determines whether the state field was parsed.
     *
     * @return <code>true</code> the state field was parsed; <code>false</code> otherwise
     */
    public boolean hasStateFieldPathExpression() {
        return stateFieldExpression != null &&
              !stateFieldExpression.isNull();
    }

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

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

        // Parse state field
        if (tolerant) {
            stateFieldExpression = parse(wordParser, UpdateItemStateFieldPathExpressionBNF.ID, tolerant);
        }
        else {
            stateFieldExpression = new StateFieldPathExpression(this, wordParser.word());
            stateFieldExpression.parse(wordParser, tolerant);
        }

        hasSpaceAfterStateFieldPathExpression = wordParser.skipLeadingWhitespace() > 0;

        // Parse '='
        hasEqualSign = wordParser.startsWith(EQUAL);

        if (hasEqualSign) {
            wordParser.moveForward(1);
            hasSpaceAfterEqualSign = wordParser.skipLeadingWhitespace() > 0;
            if (stateFieldExpression != null) {
                hasSpaceAfterStateFieldPathExpression = true;
            }
        }

        // Parse new value
        newValue = parse(wordParser, NewValueBNF.ID, tolerant);

        if (!hasSpaceAfterEqualSign && (newValue != null)) {
            hasSpaceAfterEqualSign = true;
        }
    }

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

        // State field expression
        if (stateFieldExpression != null) {
            stateFieldExpression.toParsedText(writer, actual);
        }

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

        // '='
        if (hasEqualSign) {
            writer.append(EQUAL);
        }

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

        // New value
        if (newValue != null) {
            newValue.toParsedText(writer, actual);
        }
    }
}
