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

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

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

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

    @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));
        }
    }

    @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;
    }

    @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();
    }

    @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);
    }

    @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);
        }
    }

    @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, Expression)}
     * should behaves.
     */
    private enum ParsingType {
        CASE,
        ELSE,
        WHEN
    }
}
