/*
 * Copyright (c) 2013, 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:
//     11/06/2013-2.5.1 Chris Delahunt
//       - 374771 : TREAT support
package org.eclipse.persistence.internal.expressions;

import java.io.IOException;
import java.io.Serializable;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.internal.helper.DatabaseTable;
import org.eclipse.persistence.internal.history.DecoratedDatabaseTable;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.platform.database.DB2MainframePlatform;

/**
 * Holder class storing a QueryKeyExpression representing an outer join
 * plus some data calculated by method appendFromClauseForOuterJoin.
 */
public class OuterJoinExpressionHolder implements Comparable, Serializable
{
    final ObjectExpression joinExpression;
    DatabaseTable targetTable;
    DatabaseTable sourceTable;
    DatabaseTable targetAlias;
    DatabaseTable sourceAlias;
    List<DatabaseTable> additionalTargetTables;
    List<DatabaseTable> additionalTargetAliases;
    List<Expression> additionalJoinOnExpression;
    List<Boolean> additionalTargetIsDescriptorTable;
    Boolean hasInheritance;
    List<Integer> indexList;
    // if it's a map then an additional holder created for the key.
    // mapKeyHolder is not used in sorting because there can be no outer joins out of it,
    // the main reason for it to exist is its printAdditionalJoins method.
    OuterJoinExpressionHolder mapKeyHolder;
    // indicates whether it's a mapKeyHolder
    boolean isMapKeyHolder;

    Expression outerJoinedMappingCriteria;

    // table join expressions keyed by the tables
    Map<DatabaseTable, Expression> outerJoinedAdditionalJoinCriteria;
    // used in case no corresponding outerJoinExpression is provided -
    // only multi-table inheritance should be outer joined
    ClassDescriptor descriptor;

    SQLSelectStatement statement;

    public OuterJoinExpressionHolder(SQLSelectStatement statement, ObjectExpression joinExpression, Expression outerJoinedMappingCriteria,
            Map<DatabaseTable, Expression> outerJoinedAdditionalJoinCriteria, ClassDescriptor descriptor) {
        this.statement = statement;
        this.joinExpression = joinExpression;

        this.outerJoinedMappingCriteria = outerJoinedMappingCriteria;
        this.outerJoinedAdditionalJoinCriteria = outerJoinedAdditionalJoinCriteria;
        this.descriptor = descriptor;
    }

    /*
     * Used for MapKeys
     */
    public OuterJoinExpressionHolder(OuterJoinExpressionHolder holder) {
        this.joinExpression = holder.joinExpression;

        this.outerJoinedMappingCriteria = holder.outerJoinedMappingCriteria;
        this.outerJoinedAdditionalJoinCriteria = holder.outerJoinedAdditionalJoinCriteria;
        this.descriptor = holder.descriptor;
    }

    protected void process(boolean usesHistory) {
        process(usesHistory, false);
    }

    protected void process(boolean usesHistory, boolean isMapKeyHolder) {
        this.isMapKeyHolder = isMapKeyHolder;
        if (this.joinExpression instanceof QueryKeyExpression) {
            QueryKeyExpression expression = (QueryKeyExpression)this.joinExpression;
            if (isMapKeyHolder) {
                descriptor = expression.getMapKeyDescriptor();
                this.targetTable = descriptor.getTables().get(0);
                this.targetAlias = outerJoinedMappingCriteria.aliasForTable(this.targetTable);
            } else {
                // this is a map - create a holder for the key
                if(expression.isMapKeyObjectRelationship()) {
                    this.mapKeyHolder = new OuterJoinExpressionHolder(this);
                    this.mapKeyHolder.process(usesHistory, true);
                }
                // in DirectCollection case descriptor is null
                descriptor = expression.getDescriptor();
                this.targetTable = expression.getReferenceTable();
                this.targetAlias = expression.aliasForTable(this.targetTable);
            }
            this.sourceTable = expression.getSourceTable();
            this.sourceAlias = expression.getBaseExpression().aliasForTable(this.sourceTable);
        } else if (this.joinExpression != null) {
            this.sourceTable = ((ObjectExpression)this.joinExpression.getJoinSource()).getDescriptor().getTables().get(0);
            this.sourceAlias = this.joinExpression.getJoinSource().aliasForTable(this.sourceTable);
            this.targetTable = this.joinExpression.getDescriptor().getTables().get(0);
            this.targetAlias = this.joinExpression.aliasForTable(this.targetTable);
        } else {
            // absence of join expression means that this holder used for multitable inheritance:
            //   ReadAllQuery query = new ReadAllQuery(Project.class);
            //   query.setShouldOuterJoinSubclasses(true);
            // will produce:
            //   SELECT ... FROM PROJECT t0 LEFT OUTER JOIN LPROJECT t1 ON (t1.PROJ_ID = t0.PROJ_ID)
            sourceTable = descriptor.getTables().get(0);
            targetTable = descriptor.getInheritancePolicy().getChildrenTables().get(0);
            Expression exp = outerJoinedAdditionalJoinCriteria.get(targetTable);
            sourceAlias = exp.aliasForTable(sourceTable);
            targetAlias = exp.aliasForTable(targetTable);
        }
        if(usesHistory) {
            sourceTable = getTableAliases().get(sourceAlias);
            targetTable = getTableAliases().get(targetAlias);
        }

        if(outerJoinedAdditionalJoinCriteria != null && !outerJoinedAdditionalJoinCriteria.isEmpty()) {
            if(descriptor == null) {
                descriptor = joinExpression.getDescriptor();
            }
            List<DatabaseTable> targetTables = descriptor.getTables();
            int nDescriptorTables = targetTables.size();
            hasInheritance = descriptor.hasInheritance();
            if(hasInheritance) {
                targetTables = descriptor.getInheritancePolicy().getAllTables();
            }
            int tablesSize = targetTables.size();
            // skip main table - start with i=1
            for(int i=1; i < tablesSize; i++) {
                DatabaseTable table = (DatabaseTable)targetTables.get(i);
                Expression onExpression = outerJoinedAdditionalJoinCriteria.get(table);
                if (onExpression != null) {
                    DatabaseTable alias = onExpression.aliasForTable(table);
                    if (usesHistory) {
                        table = getTableAliases().get(alias);
                    }
                    if (this.additionalTargetAliases == null) {
                        this.additionalTargetAliases = new ArrayList();
                        this.additionalTargetTables = new ArrayList();
                        this.additionalJoinOnExpression = new ArrayList();
                        this.additionalTargetIsDescriptorTable = new ArrayList();
                    }
                    this.additionalTargetAliases.add(alias);
                    this.additionalTargetTables.add(table);
                    this.additionalJoinOnExpression.add(onExpression);
                    // if it's the descriptor's own table - true; otherwise (it's the child's table) - false.
                    this.additionalTargetIsDescriptorTable.add(i < nDescriptorTables);
                }
            }
        }
    }

    public boolean hasAdditionalJoinExpressions() {
        return this.additionalTargetTables != null;
    }

    public boolean hasMapKeyHolder() {
        return this.mapKeyHolder != null;
    }

    public void createIndexList(Map<DatabaseTable, OuterJoinExpressionHolder> targetAliasToHolders, Map<DatabaseTable, Integer> aliasToIndexes) {
        if(this.indexList != null) {
            // indexList has been already created
            return;
        }

        this.indexList = new ArrayList();
        OuterJoinExpressionHolder baseHolder = targetAliasToHolders.get(this.sourceAlias);
        if(baseHolder != null) {
            baseHolder.createIndexList(targetAliasToHolders, aliasToIndexes);
            this.indexList.addAll(baseHolder.indexList);
        } else {
            this.indexList.add(aliasToIndexes.get(this.sourceAlias));
        }
        this.indexList.add(aliasToIndexes.get(this.targetAlias));
    }

    /*
     * The method should be called only on instances of OuterJoinExpressionHolder
     * and only after the indexList has been created.
     * Loop through both lists comparing the members corresponding to the same index
     * until not equal members are found.
     * If all the members are the same, but one of the lists is shorter then it's less.
     * Examples:
     * {2, 1} < {2, 2}; {2, 1} < {3}; {2, 1} > {2}
     */
    @Override
    public int compareTo(Object other) {
        if(other == this) {
            return 0;
        }
        List<Integer> otherIndexList = ((OuterJoinExpressionHolder)other).indexList;
        int nMinSize = this.indexList.size();
        int nCompare = -1;
        int nOtherSize = otherIndexList.size();
        if(nMinSize > nOtherSize) {
            nMinSize = nOtherSize;
            nCompare = 1;
        } else if(nMinSize == nOtherSize) {
            nCompare = 0;
        }
        for(int i=0; i < nMinSize; i++) {
            int index = indexList.get(i);
            int otherIndex = otherIndexList.get(i);
            if(index < otherIndex) {
                return -1;
            } else if(index > otherIndex) {
                return 1;
            }
        }
        return nCompare;
    }

    void printAdditionalJoins(ExpressionSQLPrinter printer, List<DatabaseTable> outerJoinedAliases, Collection aliasesOfTablesToBeLocked, boolean shouldPrintUpdateClauseForAllTables)  throws IOException {
        Writer writer = printer.getWriter();
        AbstractSession session = printer.getSession();

        int size = this.additionalTargetAliases.size();
        for(int i=0; i < size; i++) {
            DatabaseTable table = this.additionalTargetTables.get(i);
            if(this.additionalTargetIsDescriptorTable.get(i)) {
                // it's descriptor's own table
                if (!session.getPlatform().supportsANSIInnerJoinSyntax()) {
                    // if the DB does not support 'JOIN', do a:
                    if (this.hasInheritance) {
                        // right outer join instead. This will give the same
                        // result because the right table has no rows that
                        // are not in the left table (left table maps to the
                        // main class, right table to a subclass in an
                        // inheritance mapping with a joined subclass
                        // strategy).
                        writer.write(" RIGHT OUTER");
                    } else {
                        // left outer join instead. This will give the same
                        // result because the left table has no rows that
                        // are not in the right table (left table is either
                        // a join table or it is joining secondary tables to
                        // a primary table).
                        writer.write(" LEFT OUTER");
                    }
                }
                writer.write(" JOIN ");
            } else {
                // it's child's table
                writer.write(" LEFT OUTER JOIN ");
            }
            DatabaseTable alias = this.additionalTargetAliases.get(i);
            table.printSQL(printer);
            writer.write(" ");
            if (alias.isDecorated()) {
                ((DecoratedDatabaseTable)alias).getAsOfClause().printSQL(printer);
                writer.write(" ");
            }
            outerJoinedAliases.add(alias);
            alias.printSQL(printer);
            if (shouldPrintUpdateClauseForAllTables || (aliasesOfTablesToBeLocked != null && aliasesOfTablesToBeLocked.remove(alias))) {
                getForUpdateClause().printSQL(printer, statement/*SQLSelectStatement.this*/);
            }
            writer.write(" ON ");
            if (session.getPlatform() instanceof DB2MainframePlatform) {
                ((RelationExpression)this.additionalJoinOnExpression.get(i)).printSQLNoParens(printer);
            } else {
                this.additionalJoinOnExpression.get(i).printSQL(printer);
            }
        }
    }

    /**
     * INTERNAL:
     * Return the aliases used.
     */
    public Map<DatabaseTable, DatabaseTable> getTableAliases() {
        return statement.getTableAliases();
    }

    protected ForUpdateClause getForUpdateClause() {
        return statement.getForUpdateClause();
    }
}
