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

/**
 * <div><b>BNF:</b> <code>general_case_expression ::= CASE when_clause {when_clause}* ELSE scalar_expression END</code></div>
 * or
 * <div><b>BNF:</b> <code>simple_case_expression ::= CASE case_operand simple_when_clause {simple_when_clause}* ELSE scalar_expression END</code></div>
 *
 * @version 2.5
 * @since 2.3
 * @author Pascal Filion
 */
public final class CaseExpression extends AbstractExpression {

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

    /**
     * The {@link Expression} representing the case operand.
     */
    private AbstractExpression caseOperand;

    /**
     * The {@link Expression} representing the <b>ELSE</b> expression.
     */
    private AbstractExpression elseExpression;

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

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

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

    /**
     * Determines whether a whitespace was parsed after the case operand.
     */
    private boolean hasSpaceAfterCaseOperand;

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

    /**
     * Determines whether a whitespace was parsed after the <b>BETWEEN</b> expression.
     */
    private boolean hasSpaceAfterElseExpression;

    /**
     * Determines whether a whitespace was parsed after <b>WHEN</b> clause.
     */
    private boolean hasSpaceAfterWhenClauses;

    /**
     * Used to determine how to check if the parsing is complete.
     */
    private ParsingType parsingType;

    /**
     * The {@link Expression} representing the <b>WHEN</b> clauses.
     */
    private AbstractExpression whenClauses;

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

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

    /**
     * {@inheritDoc}
     */
    @Override
    public void acceptChildren(ExpressionVisitor visitor) {
        getCaseOperand().accept(visitor);
        getWhenClauses().accept(visitor);
        getElseExpression().accept(visitor);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void addChildrenTo(Collection<Expression> children) {
        children.add(getCaseOperand());
        children.add(getWhenClauses());
        children.add(getElseExpression());
    }

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

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

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

        // Case operand
        if (caseOperand != null) {
            children.add(caseOperand);
        }

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

        // WHEN clauses
        if (whenClauses != null) {
            children.add(whenClauses);
        }

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

        // 'ELSE'
        if (elseIdentifier != null) {
            children.add(buildStringExpression(ELSE));
        }

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

        // Else expression
        if (elseExpression != null) {
            children.add(elseExpression);
        }

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

        // 'END'
        if (endIdentifier != null) {
            children.add(buildStringExpression(END));
        }
    }

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

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

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

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

        return super.findQueryBNF(expression);
    }

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

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

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

    /**
     * Returns the {@link Expression} that represents the <b>CASE</b> operand.
     *
     * @return The expression that was parsed representing the <b>CASE</b> operand
     */
    public Expression getCaseOperand() {
        if (caseOperand == null) {
            caseOperand = buildNullExpression();
        }
        return caseOperand;
    }

    /**
     * Returns the {@link Expression} that represents the <b>ELSE</b> operand.
     *
     * @return The expression that was parsed representing the <b>ELSE</b> operand
     */
    public AbstractExpression getElseExpression() {
        if (elseExpression == null) {
            elseExpression = buildNullExpression();
        }
        return elseExpression;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public JPQLQueryBNF getQueryBNF() {
        return getQueryBNF(GeneralCaseExpressionBNF.ID);
    }

    /**
     * Returns the {@link Expression} that represents the <b>WHEN</b> clauses.
     *
     * @return The expression that was parsed representing the <b>WHEN</b> clauses
     */
    public AbstractExpression getWhenClauses() {
        if (whenClauses == null) {
            whenClauses = buildNullExpression();
        }
        return whenClauses;
    }

    /**
     * Determines whether the <b>CASE</b> operand was parsed.
     *
     * @return <code>true</code> if the <b>CASE</b> operand was parsed; <code>false</code> otherwise
     */
    public boolean hasCaseOperand() {
        return caseOperand != null &&
              !caseOperand.isNull();
    }

    /**
     * Determines whether the identifier <b>ELSE</b> was parsed.
     *
     * @return <code>true</code> if the identifier <b>ELSE</b> was parsed; <code>false</code>
     * otherwise
     */
    public boolean hasElse() {
        return elseIdentifier != null;
    }

    /**
     * Determines whether the <b>ELSE</b> expression was parsed.
     *
     * @return <code>true</code> if the <b>ELSE</b> expression was parsed; <code>false</code>
     * otherwise
     */
    public boolean hasElseExpression() {
        return elseExpression != null &&
              !elseExpression.isNull();
    }

    /**
     * Determines whether the identifier <b>END</b> was parsed.
     *
     * @return <code>true</code> if the identifier <b>END</b> was parsed; <code>false</code> otherwise
     */
    public boolean hasEnd() {
        return endIdentifier != null;
    }

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

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

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

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

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

    /**
     * Determines whether the <b>WHEN</b> clauses were parsed.
     *
     * @return <code>true</code> if the <b>WHEN</b> clauses were parsed;
     * <code>false</code> otherwise
     */
    public boolean hasWhenClauses() {
        return whenClauses != null &&
              !whenClauses.isNull();
    }

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

        // 'CASE'
        if (parsingType == ParsingType.CASE) {
            return word.equalsIgnoreCase(WHEN) ||
                   word.equalsIgnoreCase(ELSE) ||
                   word.equalsIgnoreCase(END)  ||
                   super.isParsingComplete(wordParser, word, expression);
        }

        // 'WHEN'
        if (parsingType == ParsingType.WHEN) {
            return word.equalsIgnoreCase(ELSE) ||
                   word.equalsIgnoreCase(END)  ||
                   super.isParsingComplete(wordParser, word, expression);
        }

        // 'ELSE'
        return word.equalsIgnoreCase(END) ||
               super.isParsingComplete(wordParser, word, expression);
    }

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

        // Parse 'CASE'
        caseIdentifier = wordParser.moveForward(CASE);
        hasSpaceAfterCase = wordParser.skipLeadingWhitespace() > 0;

        // Parse case operand
        parsingType = ParsingType.CASE;

        if (!wordParser.startsWithIdentifier(WHEN)) {
            caseOperand = parse(wordParser, CaseOperandBNF.ID, tolerant);
            hasSpaceAfterCaseOperand = wordParser.skipLeadingWhitespace() > 0;
        }

        // Parse the WHEN clauses
        parsingType = ParsingType.WHEN;
        whenClauses = parse(wordParser, WhenClauseBNF.ID, tolerant);
        hasSpaceAfterWhenClauses = wordParser.skipLeadingWhitespace() > 0;

        // Parse 'ELSE'
        if (!tolerant || wordParser.startsWithIdentifier(ELSE)) {
            elseIdentifier = wordParser.moveForward(ELSE);
            hasSpaceAfterElse = wordParser.skipLeadingWhitespace() > 0;
        }

        // Parse the ELSE expression
        parsingType = ParsingType.ELSE;
        elseExpression = parse(wordParser, ElseExpressionBNF.ID, tolerant);
        hasSpaceAfterElseExpression = wordParser.skipLeadingWhitespace() > 0;

        // Parse 'END'
        if (!tolerant || wordParser.startsWithIdentifier(END)) {
            endIdentifier = wordParser.moveForward(END);
        }
    }

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

        // 'CASE'
        writer.append(actual ? caseIdentifier : CASE);

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

        // Case Operand
        if (caseOperand != null) {
            caseOperand.toParsedText(writer, actual);
        }

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

        // When clauses
        if (whenClauses != null) {
            whenClauses.toParsedText(writer, actual);
        }

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

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

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

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

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

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

    /**
     * A enumeration used to determine how {@link CaseExpression#isParsingComplete(WordParser, String)}
     * should behaves.
     */
    private enum ParsingType {
        CASE,
        ELSE,
        WHEN
    }
}
