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

/**
 * The <b>EXTRACT</b> function extracts a date part from a date/time value. The date part can be
 * <code>YEAR</code>, <code>MONTH</code>, <code>DAY</code>, <code>HOUR</code>, <code>MINUTE</code>,
 * <code>SECOND</code>. Some databases may support other parts.
 *
 * <div><b>BNF:</b> <code>extract_expression ::= EXTRACT(date_part_literal [FROM] scalar_expression)</code></div>
 * <p>
 * date_part_literal ::= { MICROSECOND | SECOND | MINUTE | HOUR | DAY | WEEK | MONTH | QUARTER |
 *                         YEAR | SECOND_MICROSECOND | MINUTE_MICROSECOND | MINUTE_SECOND |
 *                         HOUR_MICROSECOND | HOUR_SECOND | HOUR_MINUTE | DAY_MICROSECOND |
 *                         DAY_SECOND | DAY_MINUTE | DAY_HOUR | YEAR_MONTH, etc }
 * </p>
 *
 * @version 2.5
 * @since 2.4
 * @author James Sutherland
 */
public final class ExtractExpression extends AbstractSingleEncapsulatedExpression {

    /**
     * The date part to extract from the date/time.
     */
    private String datePart;

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

    /**
     * Determines whether a space was parsed after the date part.
     */
    private boolean hasSpaceAfterDatePart;

    /**
     * Determines whether a space was parsed after the identifier <b>FROM</b>.
     */
    private boolean hasSpaceAfterFrom;

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

    @Override
    public void accept(ExpressionVisitor visitor) {
        acceptUnknownVisitor(visitor);
    }

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

        // Date part
        if (hasDatePart()) {
            children.add(buildStringExpression(datePart));
        }

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

        // 'FROM'
        if (fromIdentifier != null) {
            children.add(buildStringExpression(FROM));
        }

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

        // Value
        super.addOrderedEncapsulatedExpressionTo(children);
    }

    @Override
    public String getEncapsulatedExpressionQueryBNFId() {
        return ScalarExpressionBNF.ID;
    }

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

    /**
     * Returns the date part that was parsed, it is used to extract a single part of a date/time,
     * such as year, month, day, your, etc.
     *
     * @return The part of the date/time to retrieve
     */
    public String getDatePart() {
        return datePart;
    }

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

    /**
     * Determines whether the date part literal was parsed or not.
     *
     * @return <code>true</code> if the date part literal was parsed; <code>false</code> otherwise
     */
    public boolean hasDatePart() {
        return ExpressionTools.stringIsNotEmpty(datePart);
    }

    @Override
    public boolean hasEncapsulatedExpression() {
        return hasDatePart() || (fromIdentifier != null) || hasExpression();
    }

    /**
     * Determines whether the identifier <b>FROM</b> was part of the query.
     *
     * @return <code>true</code> if the identifier <b>FROM</b> was parsed; <code>false</code> otherwise
     */
    public boolean hasFrom() {
        return fromIdentifier != null;
    }

    /**
     * Determines whether a whitespace was found after the date part literal.
     *
     * @return <code>true</code> if there was a whitespace after the date part literal;
     * <code>false</code> otherwise
     */
    public boolean hasSpaceAfterDatePart() {
        return hasSpaceAfterDatePart;
    }

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

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

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

        if (wordParser.isTail()) {
            datePart = ExpressionTools.EMPTY_STRING;
            return;
        }

        // Parse the date part
        datePart = wordParser.word();

        // Invalid date part, parse it as the scalar expression
        if (tolerant &&
            (isParsingComplete(wordParser, datePart, null) ||
             datePart.indexOf(DOT) > -1 ||
             datePart.charAt(0) == SINGLE_QUOTE ||
             datePart.charAt(0) == DOUBLE_QUOTE ||
             Character.isDigit(datePart.charAt(0)))) {

            datePart = ExpressionTools.EMPTY_STRING;
            hasSpaceAfterDatePart = whitespaceCount > 0;
        }
        else {
            wordParser.moveForward(datePart);
            hasSpaceAfterDatePart = wordParser.skipLeadingWhitespace() > 0;
        }

        // Parse 'FROM'
        if (wordParser.startsWithIdentifier(FROM)) {
            fromIdentifier = wordParser.moveForward(FROM);
            hasSpaceAfterFrom = wordParser.skipLeadingWhitespace() > 0;
        }

        // Parse the value
        super.parseEncapsulatedExpression(wordParser, whitespaceCount, tolerant);
    }

    @Override
    protected void removeEncapsulatedExpression() {
        super.removeEncapsulatedExpression();
        datePart              = ExpressionTools.EMPTY_STRING;
        fromIdentifier        = null;
        hasSpaceAfterFrom     = false;
        hasSpaceAfterDatePart = false;
    }

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

        // Date part
        writer.append(datePart);

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

        // FROM
        if (fromIdentifier != null) {
            writer.append(actual ? fromIdentifier : FROM);
        }

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

        // Value
        super.toParsedTextEncapsulatedExpression(writer, actual);
    }
}
