/*
 * Copyright (c) 1998, 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 from Oracle TopLink
package org.eclipse.persistence.internal.expressions;

import java.io.BufferedWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.queries.ExpressionQueryMechanism;
import org.eclipse.persistence.internal.queries.ReportItem;
import org.eclipse.persistence.internal.queries.StatementQueryMechanism;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.queries.ReportQuery;
import org.eclipse.persistence.queries.SQLCall;

/**
 * This is used to support subselects.
 * The subselect represents a mostly independent (has own expression builder) query using a report query.
 * Subselects can be used for, in (single column), exists (empty or non-empty), comparisons (single value).
 */
public class SubSelectExpression extends BaseExpression {
    protected boolean hasBeenNormalized;

    protected ReportQuery subQuery;

    protected String attribute;
    protected Class<?> returnType;
    protected Expression criteriaBase;

    public SubSelectExpression() {
        super();
        subQuery = new ReportQuery();
    }

    public SubSelectExpression(ReportQuery query, Expression baseExpression) {
        super(baseExpression);
        this.subQuery = query;
    }

    /**
     * INTERNAL:
     * Return if the expression is equal to the other.
     * This is used to allow dynamic expression's SQL to be cached.
     */
    @Override
    public boolean equals(Object object) {
        if (this == object) {
            return true;
        }
        // Equality cannot easily be determined for sub-select expressions.
        return false;
    }

    /**
     * INTERNAL:
     * Used in debug printing of this node.
     */
    @Override
    public String descriptionOfNodeType() {
        return "SubSelect";
    }

    public ReportQuery getSubQuery() {
        initializeCountSubQuery();
        return subQuery;
    }

    /**
     * INTERNAL:
     * This method creates a report query that counts the number of values in baseExpression.anyOf(attribute)
     *
     * For most queries, a ReportQuery will be created that does a simple count using an anonymous query.  In the case of
     * a DirectCollectionMapping, the ReportQuery will use the baseExpression to create a join to the table
     * containing the Direct fields and count based on that join.
     */
    protected void initializeCountSubQuery(){
        if (criteriaBase != null && (subQuery.getItems() == null || subQuery.getItems().isEmpty())){
            if (baseExpression.getSession() != null && ((ObjectExpression)baseExpression).getDescriptor() != null){
                Class<?> sourceClass = ((ObjectExpression)baseExpression).getDescriptor().getJavaClass();
                ClassDescriptor descriptor = baseExpression.getSession().getDescriptor(sourceClass);
                if (descriptor != null){
                    DatabaseMapping mapping = descriptor.getMappingForAttributeName(attribute);
                    if (mapping != null && mapping.isDirectCollectionMapping()){
                        subQuery.setExpressionBuilder(baseExpression.getBuilder());
                        subQuery.setReferenceClass(sourceClass);
                        subQuery.addCount(attribute, subQuery.getExpressionBuilder().anyOf(attribute), returnType);
                        return;
                    }
                }
             }
            // Use an anonymous subquery that will get its reference class
            // set during SubSelectExpression.normalize.
             subQuery.addCount("COUNT", subQuery.getExpressionBuilder(), returnType);
             if (attribute != null){
                 subQuery.setSelectionCriteria(subQuery.getExpressionBuilder().equal(criteriaBase.anyOf(attribute)));
             } else {
                 subQuery.setSelectionCriteria(subQuery.getExpressionBuilder().equal(criteriaBase));
             }
        }
    }

    /**
     * INTERNAL:
     */
    @Override
    public boolean isSubSelectExpression() {
        return true;
    }

    /**
     * INTERNAL:
     * For iterating using an inner class
     */
    @Override
    public void iterateOn(ExpressionIterator iterator) {
        super.iterateOn(iterator);
        if (baseExpression != null) {
            baseExpression.iterateOn(iterator);
        }

        // For Flashback: It is now possible to create iterators that will span
        // the entire expression, even the where clause embedded in a subQuery.
        if (iterator.shouldIterateOverSubSelects()) {
            if (getSubQuery().getSelectionCriteria() != null) {
                getSubQuery().getSelectionCriteria().iterateOn(iterator);
            } else {
                getSubQuery().getExpressionBuilder().iterateOn(iterator);
            }
        }
    }

    /**
     * INTERNAL:
     * The subquery must be normalized with the knowledge of the outer statement for outer references and correct aliasing.
     * For CR#4223 it will now be normalized after the outer statement is, rather than
     * somewhere in the middle of the outer statement's normalize.
     */
    @Override
    public Expression normalize(ExpressionNormalizer normalizer) {
        if (this.hasBeenNormalized) {
            return this;
        }
        //has no effect but validateNode is here for consistency
        validateNode();
        // Defer normalization of this expression until later.
        normalizer.addSubSelectExpression(this);
        normalizer.getStatement().setRequiresAliases(true);
        return this;
    }

    /**
     * INTERNAL:
     * Normalize this expression now that the parent statement has been normalized.
     * For CR#4223
     */
    public Expression normalizeSubSelect(ExpressionNormalizer normalizer, Map clonedExpressions) {
        if (this.hasBeenNormalized) {
            return this;
        }
        this.hasBeenNormalized = true;
        normalizer.getStatement().setRequiresAliases(true);
        // Anonymous subqueries: The following is to support sub-queries created
        // on the fly by OSQL Expressions isEmpty(), isNotEmpty(), size().
        if (!getSubQuery().isCallQuery() && (getSubQuery().getReferenceClass() == null)) {
            ReportQuery subQuery = getSubQuery();
            Expression criteria = subQuery.getSelectionCriteria();

            // The criteria should be of form builder.equal(exp), where exp belongs
            // to the parent statement and has already been normalized, hence it
            // knows its reference class.
            if (criteria instanceof LogicalExpression) {
                criteria = ((LogicalExpression)criteria).getFirstChild();
            }
            if (criteria instanceof RelationExpression) {
                Expression rightChild = ((RelationExpression)criteria).getSecondChild();
                if (rightChild instanceof QueryKeyExpression) {
                    ClassDescriptor descriptor = ((QueryKeyExpression)rightChild).getDescriptor();
                    // descriptor will be null here for query key expressions
                    if (descriptor ==null){
                        descriptor = ((ObjectExpression)((QueryKeyExpression)rightChild).getBaseExpression()).getDescriptor();
                    }
                    subQuery.setReferenceClass(descriptor.getJavaClass());
                }
            }
        }

        //has no effect but validateNode is here for consistency
        validateNode();
        getSubQuery().prepareSubSelect(normalizer.getSession(), null, clonedExpressions);
        if (!getSubQuery().isCallQuery()) {
            SQLSelectStatement statement = (SQLSelectStatement)((StatementQueryMechanism)getSubQuery().getQueryMechanism()).getSQLStatement();

            // setRequiresAliases was already set for parent statement.
            statement.setRequiresAliases(true);
            statement.setParentStatement(normalizer.getStatement());
            statement.normalize(normalizer.getSession(), getSubQuery().getDescriptor(), clonedExpressions);
        }
        return this;
    }

    /**
     * The query must be cloned, and the sub-expression must be cloned using the same outer expression identity.
     */
    @Override
    protected void postCopyIn(Map alreadyDone) {
        initializeCountSubQuery();
        super.postCopyIn(alreadyDone);
        ReportQuery clonedQuery = (ReportQuery)getSubQuery().clone();
        if (!clonedQuery.isCallQuery()) {
            if (clonedQuery.getSelectionCriteria() != null) {
                clonedQuery.setSelectionCriteria(getSubQuery().getSelectionCriteria().copiedVersionFrom(alreadyDone));
                // ensure the builder for the subquery is the same as the builder for the subquery's expression
                // for certain Subqueries (for instance batch queries for direct collections), when we get to this
                // point the builder for the clonedQuery will already be aliased.  Replacing the builder with
                // the builder for the query's new expression solves this issue.
                if (clonedQuery.getExpressionBuilder() != null) {
                    clonedQuery.setExpressionBuilder((ExpressionBuilder)clonedQuery.getExpressionBuilder().copiedVersionFrom(alreadyDone));
                }
            } else if (clonedQuery.getExpressionBuilder() != null) {
                // Must clone the expression builder.
                clonedQuery.setExpressionBuilder((ExpressionBuilder)clonedQuery.getExpressionBuilder().copiedVersionFrom(alreadyDone));
            }
            // Must also clone report items, group by, having, order by.
            clonedQuery.copyReportItems(alreadyDone);
        }
        setSubQuery(clonedQuery);
    }

    /**
     * Print the sub query to the printer.
     */
    protected void printCustomSQL(ExpressionSQLPrinter printer) {
        /*
         * modified for bug#2658466.  This fix ensures that Custom SQL sub-queries are translated
         * and have variables substituted with values correctly.
         */
        SQLCall call = (SQLCall)getSubQuery().getCall();
        call.translateCustomQuery();
        printer.getCall().getParameters().addAll(call.getParameters());
        printer.getCall().getParameterTypes().addAll(call.getParameterTypes());
        printer.printString(call.getCallString());
    }

    /**
     * Print the sub query to the printer.
     */
    @Override
    public void printSQL(ExpressionSQLPrinter printer) {
        ReportQuery query = getSubQuery();
        printer.printString("(");
        if (query.isCallQuery()) {
            printCustomSQL(printer);
        } else {
            SQLSelectStatement statement = (SQLSelectStatement)((ExpressionQueryMechanism)query.getQueryMechanism()).getSQLStatement();
            boolean isFirstElementPrinted = printer.isFirstElementPrinted();
            printer.setIsFirstElementPrinted(false);
            boolean requiresDistinct = printer.requiresDistinct();
            statement.printSQL(printer);
            printer.setIsFirstElementPrinted(isFirstElementPrinted);
            printer.setRequiresDistinct(requiresDistinct);
        }
        printer.printString(")");
    }

    /**
     * Should not rebuild as has its on expression builder.
     */
    @Override
    public Expression rebuildOn(Expression newBase) {
        // TODO: This should be using rebuildOn not twist, but needs to pass the oldBase to rebuildOn
        // and only the oldBase should be replaced with the new base.
        // Further the twist, rebuildOn, and copy are doing essentially the same thing
        // and should be merged into a single method instead of having three methods doing the same thing 3 different ways
        // and all having various different bugs in them.
        SubSelectExpression subSelect = (SubSelectExpression) shallowClone();

        // Rebuild base expression
        subSelect.setBaseExpression(getBaseExpression().rebuildOn(newBase));

        // Clone report query
        ReportQuery reportQuery = (ReportQuery) getSubQuery().clone();

        // Twist report items
        List<ReportItem> newItems = new ArrayList<>(getSubQuery().getItems().size());

        for (ReportItem item : reportQuery.getItems()) {
            newItems.add(new ReportItem(item.getName(), item.getAttributeExpression().twistedForBaseAndContext(newBase, getBuilder(), getBaseExpression())));
        }

        reportQuery.setItems(newItems);

        // Twist group by expressions
        if (reportQuery.hasGroupByExpressions()) {
            List<Expression> groupByExpressions = new ArrayList<>(reportQuery.getGroupByExpressions().size());
            for (Expression groupByExpression : reportQuery.getGroupByExpressions()) {
                groupByExpressions.add(groupByExpression.twistedForBaseAndContext(newBase, getBuilder(), getBaseExpression()));
            }

            reportQuery.setGroupByExpressions(groupByExpressions);
        }

        // Twist order by expressions
        if (reportQuery.hasOrderByExpressions()) {
            List<Expression> orderByExpressions = new ArrayList<>(reportQuery.getOrderByExpressions().size());
            for (Expression orderByExpression : reportQuery.getOrderByExpressions()) {
                orderByExpressions.add(orderByExpression.twistedForBaseAndContext(newBase, getBuilder(), getBaseExpression()));
            }

            reportQuery.setOrderByExpressions(orderByExpressions);
        }

        // Twist union expressions
        if (reportQuery.hasUnionExpressions()) {
            List<Expression> unionExpressions = new ArrayList<>(reportQuery.getUnionExpressions().size());
            for (Expression unionExpression : reportQuery.getUnionExpressions()) {
                unionExpressions.add(unionExpression.twistedForBaseAndContext(newBase, getBuilder(), getBaseExpression()));
            }

            reportQuery.setUnionExpressions(unionExpressions);
        }

        // Twist selection criteria
        if (reportQuery.getSelectionCriteria() != null) {
            reportQuery.setSelectionCriteria(reportQuery.getSelectionCriteria().twistedForBaseAndContext(newBase, getBuilder(), getBaseExpression()));
        }

        // Set the cloned report query
        subSelect.setSubQuery(reportQuery);

        return subSelect;
    }

    /**
     * INTERNAL:
     * Search the tree for any expressions (like SubSelectExpressions) that have been
     * built using a builder that is not attached to the query.  This happens in case of an Exists
     * call using a new ExpressionBuilder().  This builder needs to be replaced with one from the query.
     */
    @Override
    public void resetPlaceHolderBuilder(ExpressionBuilder queryBuilder){
        if(this.baseExpression.isExpressionBuilder() && ((ExpressionBuilder)this.baseExpression).wasQueryClassSetInternally()){
            this.baseExpression = queryBuilder;
            if (this.builder != null){
                this.builder = queryBuilder;
            }
        }else{
            this.baseExpression.resetPlaceHolderBuilder(queryBuilder);
        }
    }

    public void setSubQuery(ReportQuery subQuery) {
        this.subQuery = subQuery;
    }

    @Override
    public Expression twistedForBaseAndContext(Expression newBase, Expression context, Expression oldBase) {
        SubSelectExpression subSelect = (SubSelectExpression) shallowClone();

        // Twist base expression
        subSelect.setBaseExpression(subSelect.getBaseExpression().twistedForBaseAndContext(newBase, context, oldBase));

        // Clone report query
        ReportQuery reportQuery = (ReportQuery) getSubQuery().clone();

        // Twist report items
        List<ReportItem> newItems = new ArrayList<>(getSubQuery().getItems().size());

        for (ReportItem item : getSubQuery().getItems()) {
            newItems.add(new ReportItem(item.getName(), item.getAttributeExpression().twistedForBaseAndContext(newBase, context, getBaseExpression())));
        }

        reportQuery.setItems(newItems);

        // Twist group by expressions
        if (getSubQuery().hasGroupByExpressions()) {
            List<Expression> groupByExpressions = new ArrayList<>(getSubQuery().getGroupByExpressions().size());
            for (Expression groupByExpression : getSubQuery().getGroupByExpressions()) {
                groupByExpressions.add(groupByExpression.twistedForBaseAndContext(newBase, context, getBaseExpression()));
            }

            reportQuery.setGroupByExpressions(groupByExpressions);
        }

        // Twist order by expressions
        if (getSubQuery().hasOrderByExpressions()) {
            List<Expression> orderByExpressions = new ArrayList<>(getSubQuery().getOrderByExpressions().size());
            for (Expression orderByExpression : getSubQuery().getOrderByExpressions()) {
                orderByExpressions.add(orderByExpression.twistedForBaseAndContext(newBase, context, getBaseExpression()));
            }

            reportQuery.setOrderByExpressions(orderByExpressions);
        }

        // Twist union expressions
        if (getSubQuery().hasUnionExpressions()) {
            List<Expression> unionByExpressions = new ArrayList<>(getSubQuery().getUnionExpressions().size());
            for (Expression unionExpression : getSubQuery().getUnionExpressions()) {
                unionByExpressions.add(unionExpression.twistedForBaseAndContext(newBase, context, getBaseExpression()));
            }

            reportQuery.setUnionExpressions(unionByExpressions);
        }

        // Twist selection criteria
        if (getSubQuery().getSelectionCriteria() != null) {
            reportQuery.setSelectionCriteria(getSubQuery().getSelectionCriteria().twistedForBaseAndContext(newBase, context, getBaseExpression()));
        }

        // Set the clones report query
        subSelect.setSubQuery(reportQuery);

        return subSelect;
    }

    /**
     * INTERNAL:
     * Used to print a debug form of the expression tree.
     */
    @Override
    public void writeDescriptionOn(BufferedWriter writer) throws IOException {
        writer.write(String.valueOf(getSubQuery()));
    }

    /**
     * INTERNAL:
     * Used in SQL printing.
     */
    @Override
    public void writeSubexpressionsTo(BufferedWriter writer, int indent) throws IOException {
        if (getSubQuery().getSelectionCriteria() != null) {
            getSubQuery().getSelectionCriteria().toString(writer, indent);
        }
    }

    /**
     * INTERNAL: called from SQLSelectStatement.writeFieldsFromExpression(...)
     * This allows a sub query in the select clause.
     */
    @Override
    public void writeFields(ExpressionSQLPrinter printer, List<DatabaseField> newFields, SQLSelectStatement statement) {
        //print ", " before each selected field except the first one
        if (printer.isFirstElementPrinted()) {
            printer.printString(", ");
        } else {
            printer.setIsFirstElementPrinted(true);
        }

        // This field is complex so any name can be used.
        DatabaseField field = new DatabaseField("*");
        field.setSqlType(DatabaseField.NULL_SQL_TYPE);
        newFields.add(field);

        printSQL(printer);
    }

    /**
     * INTERNAL:
     * This factory method is used to build a subselect that will do a count.
     * It will count the number of items in baseExpression.anyOf(attribute).
     */
    public static SubSelectExpression createSubSelectExpressionForCount(Expression outerQueryBaseExpression, Expression outerQueryCriteria, String attribute, Class<?> returnType){
        SubSelectExpression expression = new SubSelectExpression();
        expression.setBaseExpression(outerQueryBaseExpression);
        expression.attribute = attribute;
        expression.criteriaBase = outerQueryCriteria;
        if (returnType != null){
            expression.returnType = returnType;
        }
        return expression;
    }
}
