/*
 * Copyright (c) 2016, 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.BufferedWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.InheritancePolicy;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.DatabaseTable;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.queries.DatabaseQuery;

/**
 * @author cdelahun
 *
 */
public class TreatAsExpression extends QueryKeyExpression {
    protected ObjectExpression typeExpressionBase;
    protected Expression typeExpression;

    protected Boolean isDowncast;//we only need a type expression if this is a downcast.

    @Override
    public Expression convertToUseOuterJoin() {
        typeExpressionBase.convertToUseOuterJoin();
        return this;
    }

    @Override
    public String descriptionOfNodeType() {
        return "Treat";
    }

    @Override
    public boolean equals(Object object) {
        if (!super.equals(object)) {
            return false;
        }
        TreatAsExpression expression = (TreatAsExpression) object;
        return getCastClass().equals(expression.getCastClass());
    }

    @Override
    public Vector getFields() {
        return typeExpressionBase.getFields();
    }

    @Override
    public Object getFieldValue(Object objectValue, AbstractSession session) {
        return typeExpressionBase.getFieldValue(objectValue, session);
    }

    /**
     * This owns (can access) the child's extra tables as well as its parent's tables
     * so we should pull these from super (which gets them from the current descriptor)
     */
    @Override
    public List<DatabaseTable> getOwnedTables() {
        return super.getOwnedTables();
    }

    @Override
    public Expression getAlias(Expression subSelect) {
        return typeExpressionBase.getAlias(subSelect);
    }

    /**
     * Calculate the relation table for based on the various QueryKeyExpression
     * usages (join query keys, custom defined query keys, or query keys for
     * mappings).
     * Does not apply to Treat
     *
     * Called from {@link SQLSelectStatement#appendFromClauseForOuterJoin}.
     *
     * @return DatabaseTable
     */
    @Override
    public DatabaseTable getRelationTable() {
        return null;
    }

    @Override
    public TableAliasLookup getTableAliases() {
        return typeExpressionBase.getTableAliases();
    }

    @Override
    public boolean hasAsOfClause() {
        return typeExpressionBase.hasAsOfClause();
    }

    /**
     * INTERNAL:
     */
    public boolean isDowncast() {
        if (this.isDowncast == null) {
            this.getDescriptor();//initializes isDowncast
        }
        return this.isDowncast;
    }

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

    @Override
    public void printSQL(ExpressionSQLPrinter printer) {
        typeExpressionBase.printSQL(printer);
    }

    @Override
    public boolean selectIfOrderedBy() {
        return typeExpressionBase.selectIfOrderedBy();
    }

    @Override
    public Expression twistedForBaseAndContext(Expression newBase,
            Expression context, Expression oldBase) {
        if (oldBase == null || this.typeExpressionBase == oldBase) {
            Expression twistedBase = this.typeExpressionBase.twistedForBaseAndContext(newBase, context, oldBase);
            TreatAsExpression result = (TreatAsExpression)twistedBase.treat(this.castClass);
            if (shouldUseOuterJoin) {
                result.doUseOuterJoin();
            }
            if (shouldQueryToManyRelationship) {
                result.doQueryToManyRelationship();
            }
            return result;
        }

        return this;
    }

    @Override
    public void validateNode() {
        typeExpressionBase.validateNode();
        //getDescriptor currently checks if the descriptor can be found for the castclass.
        //We may want to check that this is a downcast in future
        getDescriptor();
    }

    @Override
    public Object valueFromObject(Object object, AbstractSession session,
            AbstractRecord translationRow, int valueHolderPolicy,
            boolean isObjectUnregistered) {
        return typeExpressionBase.valueFromObject(object, session,
                translationRow, valueHolderPolicy, isObjectUnregistered);
    }

    @Override
    public Object valueFromObject(Object object, AbstractSession session,
            AbstractRecord translationRow, int valueHolderPolicy) {
        return typeExpressionBase.valueFromObject(object, session,
                translationRow, valueHolderPolicy);
    }

    @Override
    public void writeDescriptionOn(BufferedWriter writer) throws IOException {
        if (castClass != null){
            writer.write(" AS "+ castClass.getName());
        }
    }

    @Override
    public void writeFields(ExpressionSQLPrinter printer, List<DatabaseField> newFields, SQLSelectStatement statement) {
        typeExpressionBase.writeFields(printer, newFields, statement);
    }

    @Override
    public void writeSubexpressionsTo(BufferedWriter writer, int indent)
            throws IOException {
        if (this.typeExpressionBase != null) {
            this.typeExpressionBase.toString(writer, indent);
        } else {
            super.writeSubexpressionsTo(writer, indent);
        }
    }

    @Override
    public ClassDescriptor getLeafDescriptor(DatabaseQuery query,
            ClassDescriptor rootDescriptor, AbstractSession session) {
        return session.getDescriptor(castClass);
    }

    @Override
    public DatabaseMapping getLeafMapping(DatabaseQuery query,
            ClassDescriptor rootDescriptor, AbstractSession session) {
        return typeExpressionBase
                .getLeafMapping(query, rootDescriptor, session);
    }

    @Override
    public DatabaseTable aliasForTable(DatabaseTable table) {
        return typeExpressionBase.aliasForTable(table);
    }

    /**
     * INTERNAL:
     * This expression is built on a different base than the one we want. Rebuild it and
     * return the root of the new tree
     */
    @Override
    public Expression rebuildOn(Expression newBase) {
        Expression newLocalBase = this.typeExpressionBase.rebuildOn(newBase);
        return newLocalBase.treat(castClass);
    }

    @Override
    public ClassDescriptor getDescriptor() {
        if (isAttribute()) {
            //TODO: add support for treat on attributes
            throw QueryException.couldNotFindCastDescriptor(castClass, getBaseExpression());
        }
        if (descriptor == null) {
            ClassDescriptor rootDescriptor = typeExpressionBase.getDescriptor();
            descriptor = convertToCastDescriptor(rootDescriptor, getSession());
        }
        return descriptor;
    }

    /**
     * INTERNAL -
     * Return the descriptor which contains this query key, look in the inheritance hierarchy
     * of rootDescriptor for the descriptor.  Does not set the descriptor, only returns it.
     */
    @Override
    public ClassDescriptor convertToCastDescriptor(ClassDescriptor rootDescriptor, AbstractSession session) {
        isDowncast = Boolean.FALSE;
        if (castClass == null || rootDescriptor == null || rootDescriptor.getJavaClass() == castClass) {
            return rootDescriptor;
        }

        ClassDescriptor castDescriptor = session.getClassDescriptor(castClass);

        if (castDescriptor == null){
            throw QueryException.couldNotFindCastDescriptor(castClass, getBaseExpression());
        }
        if (!castDescriptor.hasInheritance()){
            throw QueryException.castMustUseInheritance(getBaseExpression());
        }
        ClassDescriptor parentDescriptor = castDescriptor.getInheritancePolicy().getParentDescriptor();
        while (parentDescriptor != null){
            if (parentDescriptor == rootDescriptor){
                isDowncast = Boolean.TRUE;
                return castDescriptor;
            }
            parentDescriptor = parentDescriptor.getInheritancePolicy().getParentDescriptor();
        }
        //is there value casting an emp to person in a query?
        ClassDescriptor childDescriptor = rootDescriptor;
        while (childDescriptor != null){
            if (childDescriptor == castDescriptor){
                return rootDescriptor;
            }
            childDescriptor = childDescriptor.getInheritancePolicy().getParentDescriptor();
        }

        throw QueryException.couldNotFindCastDescriptor(castClass, getBaseExpression());
    }

    public Expression getTypeClause() {
        if (typeExpression == null) {
            if (getDescriptor() !=null && isDowncast()) {
                InheritancePolicy ip = this.getDescriptor().getInheritancePolicy();
                if (ip.isChildDescriptor()) {//or use the isDowncast flag.  Don't need to do anything if its not a downcast
                    //equivalent to typeExpressionBase.type().in(this.getDescriptor().getInheritancePolicy().getChildClasses())
                    typeExpression = ip.getWithAllSubclassesExpression();
                    if (typeExpression == null ) {
                        typeExpression = typeExpressionBase.type().equal(this.getDescriptor().getJavaClass());
                    } else {
                        typeExpression = this.typeExpressionBase.twist(typeExpression, typeExpressionBase);
                    }

                }
            } else {
                typeExpression = this.getBuilder();//equivalent to an empty expression.
            }

        }
        return typeExpression;
    }

    @Override
    protected void postCopyIn(Map alreadyDone) {
        super.postCopyIn(alreadyDone);
        this.typeExpressionBase = (ObjectExpression)typeExpressionBase.copiedVersionFrom(alreadyDone);
    }

    public TreatAsExpression(Class castClass, ObjectExpression baseExpression) {
        super();
        this.name = "Treat as "+castClass;
        this.typeExpressionBase = baseExpression;
        if (baseExpression.isExpressionBuilder()){
            this.baseExpression = baseExpression;

            shouldQueryToManyRelationship = false;
            hasQueryKey = false;
            hasMapping = false;
        } else {
            this.baseExpression = baseExpression.getBaseExpression();
        }
        shouldUseOuterJoin = true;//this uses outerjoins to the cast class' tables by default.
        this.castClass = castClass;
    }

    /**
     * INTERNAL:
     * Print java for project class generation
     */
    @Override
    public void printJava(ExpressionJavaPrinter printer) {
        this.typeExpressionBase.printJava(printer);
        if (castClass != null){
            printer.printString(".treat(" + castClass.getName() + ".class)");
        }
    }

    /**
     * INTERNAL:
     * Alias a particular table within this node
     */
    @Override
    protected void assignAlias(DatabaseTable alias, DatabaseTable table) {
        if (tableAliases == null) {
            if (this.typeExpressionBase!=null) {
                if (this.typeExpressionBase.getTableAliases()==null) {
                    typeExpressionBase.setTableAliases(new TableAliasLookup());
                }
                tableAliases = typeExpressionBase.getTableAliases();
            } else {
                tableAliases = new TableAliasLookup();
            }
        }
        tableAliases.put(alias, table);
    }

    /**
     * INTERNAL:
     * Assign aliases to any tables which I own. Start with t(initialValue),
     * and return the new value of  the counter , i.e. if initialValue is one
     * and I have tables ADDRESS and EMPLOYEE I will assign them t1 and t2 respectively, and return 3.
     */
    @Override
    public int assignTableAliasesStartingAt(int initialValue) {
        //This assumes that the typeExpressionBase will alias its own tables, so we only need to handle
        //the extra's caused by this treat expression.
        if (hasBeenAliased()) {
            return initialValue;
        }
        int counter = initialValue;
        if (this.typeExpressionBase != null) {
            counter = this.typeExpressionBase.assignTableAliasesStartingAt(counter);
        }
        //Only difference between this and ObjectExpression's assignTableAliasesStartingAt is this uses getOwnedSubTables
        // instead of getOwnedTables which returns everything.
        List<DatabaseTable> ownedTables = getOwnedSubTables();
        if (ownedTables != null) {
            for (DatabaseTable table : ownedTables) {
                assignAlias("t" + counter, table);
                counter++;
            }
        }
        this.hasBeenAliased = true;
        return counter;
    }

    /**
     * INTERNAL:
     * much like getOwnedTables(), this gets the tables represented from the descriptor.  Difference is this only returns local tables
     * for the child casted descriptor, and excludes tables owned by the parent descriptor
     */
    public List<DatabaseTable> getOwnedSubTables() {
        ClassDescriptor parentDescriptor = this.typeExpressionBase.getDescriptor();
        Vector<DatabaseTable> childTables = new Vector(2);
        if (parentDescriptor.hasInheritance() && parentDescriptor.getInheritancePolicy().hasMultipleTableChild() ) {
            List<DatabaseTable> parentTables = typeExpressionBase.getOwnedTables();
            //All tables for this child, including parent tables
            Vector<DatabaseTable> tables = getDescriptor().getTables();
            for (DatabaseTable table : tables) {
                if (!parentTables.contains(table)) {
                    childTables.add(table);
                }
            }
        }

        return childTables;
    }


    @Override
    public List<DatabaseTable> getAdditionalTables() {
        //called from ObjectExpression's getOwnedTables but not relevant to treat.
        return null;
    }

    /*
     * INTERNAL:
     * If this query key represents a foreign reference answer the
     * base expression -> foreign reference join criteria.
     * This shouldn't be used on Treat
     */
    @Override
    public Expression mappingCriteria(Expression base) {
        if (typeExpressionBase.isQueryKeyExpression()) {
            return ((QueryKeyExpression)typeExpressionBase).mappingCriteria(base);
        }
        return null;
    }

    /**
     * INTERNAL:
     * Used in case outer joins should be printed in FROM clause.
     * Each of the additional tables mapped to expressions that joins it.
     */
    public Map additionalTreatExpressionCriteriaMap() {
        if (getDescriptor() == null) {
            return null;
        }
        int tableSize = 0;
        HashMap tablesJoinExpressions = new HashMap();

        ClassDescriptor parentDescriptor = this.typeExpressionBase.getDescriptor();

        //outerjoin our parent->child tables
        if (parentDescriptor.hasInheritance() &&
                parentDescriptor.getInheritancePolicy().hasMultipleTableChild() ) {
            Vector<DatabaseTable> tables = getDescriptor().getTables();//All this child's tables
            tableSize = tables.size();
            //look up the joins from the parent descriptor to our tables.
            for (int i=0; i < tableSize; i++) {
                DatabaseTable table = tables.elementAt(i);
                Expression joinExpression = parentDescriptor.getInheritancePolicy().getChildrenTablesJoinExpressions().get(table);
                //Some of our tables might be the in our parent as well, so ignore the lack of a joinExpression
                if (joinExpression != null) {
                    joinExpression = this.baseExpression.twist(joinExpression, this);
                    tablesJoinExpressions.put(table, joinExpression);
                }
            }
        }

        if (isUsingOuterJoinForMultitableInheritance()) {
            List<DatabaseTable> childrenTables = getDescriptor().getInheritancePolicy().getChildrenTables();
            tableSize = childrenTables.size();
            for (int i=0; i < tableSize; i++) {
                DatabaseTable table = childrenTables.get(i);
                Expression joinExpression = getDescriptor().getInheritancePolicy().getChildrenTablesJoinExpressions().get(table);
                joinExpression = this.baseExpression.twist(joinExpression, this);
                tablesJoinExpressions.put(table, joinExpression);
            }
        }

        return tablesJoinExpressions;
    }

    /**
     * INTERNAL:
     * this returns a single expression to represent the join from the main table to all child descriptor tables
     * Only if outer joins should be printed in the where clause
     * @return Expression
     */
    public Expression getTreatCriteria() {
        if (getDescriptor() == null) {
            return null;
        }
        //need to build this using just the multiple tables on this descriptor not included in the parent's join expression
        Expression criteria = null;
        if(getSession().getPlatform().shouldPrintOuterJoinInWhereClause()) {
            Vector<DatabaseTable> tables = getDescriptor().getTables();//This child's tables
            ClassDescriptor parentDescriptor = this.typeExpressionBase.getDescriptor();
            int tablesSize = tables.size();
            if (parentDescriptor.hasInheritance() &&
                    parentDescriptor.getInheritancePolicy().hasMultipleTableChild() ) {
                //look up the joins from the parent descriptor to our tables.
                for (int i=0; i < tablesSize; i++) {
                    DatabaseTable table = tables.elementAt(i);
                    Expression joinExpression = parentDescriptor.getInheritancePolicy().getChildrenTablesJoinExpressions().get(table);
                    //Some of our tables might be the in our parent as well, so ignore the lack of a joinExpression
                    if (joinExpression != null) {
                        joinExpression = this.baseExpression.twist(joinExpression, this);
                        if (shouldUseOuterJoin()) {
                            joinExpression = joinExpression.convertToUseOuterJoin();
                        }
                        criteria = joinExpression.and(criteria);
                    }
                }
            }
        }
        return criteria;
    }

    /**
     * INTERNAL:
     * Return the expression to join the main table of this node to any auxiliary tables.
     */
    public Expression additionalTreatExpressionCriteria() {
        if (getDescriptor() == null) {
            return null;
        }
        //need to build this using just the multiple tables on this descriptor not included in the parent's join expression
        Expression criteria = null;
        if(getSession().getPlatform().shouldPrintOuterJoinInWhereClause()) {
            if(isUsingOuterJoinForMultitableInheritance()) {
                criteria = getDescriptor().getInheritancePolicy().getChildrenJoinExpression();
                criteria = this.baseExpression.twist(criteria, this);
                criteria.convertToUseOuterJoin();
            }
        }
        return criteria;
    }


    @Override
    public DatabaseTable getSourceTable() {
        //not used currently, but should return the baseExpressionType table if used in the future
        return null;
    }

    @Override
    public DatabaseTable getReferenceTable() {
        //not used currently, but should return the treat subclass first table if used in the future
        return null;
    }

    @Override
    public Expression normalize(ExpressionNormalizer normalizer, Expression base, List<Expression> foreignKeyJoinPointer) {
        //need to determine what type this is, as it may need to change the expression its based off slightly
        if (this.hasBeenNormalized) {
            return this;
        }
        this.hasBeenNormalized = true;

        Expression typeExpression = getTypeClause();
        typeExpression.normalize(normalizer);

        if (this.baseExpression != null) {//should never be null
            // First normalize the base.
            setBaseExpression(this.baseExpression.normalize(normalizer));
            if (getAsOfClause() == null) {
                asOf(this.baseExpression.getAsOfClause());
            }
        }

        //This class has no validation but we should still make the method call for consistency
        //bug # 2956674
        //validation is moved into normalize to ensure that expressions are valid before we attempt to work with them
        validateNode();
        //the following is based on QueryKey.normalize

        SQLSelectStatement statement = normalizer.getStatement();
        //no longer directly normalize the typeExpressionBase, or find a way to use it
        this.typeExpressionBase = (ObjectExpression)this.typeExpressionBase.normalize(normalizer);


        // Normalize the ON clause if present.  Need to use rebuild, not twist as parameters are real parameters.
        if (this.onClause != null) {//not sure this is needed/valid
            this.onClause = this.onClause.normalize(normalizer);
        }

        ClassDescriptor parentDescriptor = this.typeExpressionBase.getDescriptor();
        boolean isSTI =  getOwnedSubTables().isEmpty();
        //only really valid if it has inheritance, but better this code than skipping it into the joins

        if (isSTI) {
            if (foreignKeyJoinPointer != null) {
                // If this expression is right side of an objExp.equal(objExp), one
                // need not add additionalExpressionCriteria twice.
                // Also the join will replace the original objExp.equal(objExp).
                // For CR#2456.
                foreignKeyJoinPointer.add(typeExpression.and(this.onClause));
            } else {
                //this just and's in the entire expression to the normalizer's expression.
                //Need to use this for TYPE and none-outerjoin components
                normalizer.addAdditionalLocalExpression(typeExpression.and(this.onClause));
            }
            return this;
        }

        //if shouldPrintOuterJoinInWhereClause is true, this is this child's tables joined together in one expression
        Expression treatJoinTableExpressions = getTreatCriteria();

        boolean parentUsingOuterJoinForMultitableInheritance = typeExpressionBase.isUsingOuterJoinForMultitableInheritance();

        if (treatJoinTableExpressions != null) {
            treatJoinTableExpressions = treatJoinTableExpressions.normalize(normalizer);
        }
        Integer postition = typeExpressionBase.getOuterJoinExpIndex();
        if (postition!=null ) {
            if (parentUsingOuterJoinForMultitableInheritance) {
                //outer join was done, so our class' tables would have been included
                return this;
            }

            if (getSession().getPlatform().isInformixOuterJoin()) {
                normalizer.addAdditionalLocalExpression(typeExpression.and(additionalTreatExpressionCriteria()).and(this.onClause));
                return this;
            } else if (((!getSession().getPlatform().shouldPrintOuterJoinInWhereClause()))
                    || (!getSession().getPlatform().shouldPrintInnerJoinInWhereClause())) {

                //Adds the left joins from treat to the base QKE joins.
                Map<DatabaseTable, Expression> map = statement.getOuterJoinExpressionsHolders().get(postition).outerJoinedAdditionalJoinCriteria;
                if (map !=null) {
                    map.putAll(additionalTreatExpressionCriteriaMap());
                } else {
                    statement.getOuterJoinExpressionsHolders().get(postition).outerJoinedAdditionalJoinCriteria = additionalTreatExpressionCriteriaMap();
                }
                return this;
            }
        } else if (!getSession().getPlatform().shouldPrintOuterJoinInWhereClause()
                || (!getSession().getPlatform().shouldPrintInnerJoinInWhereClause())) {
            //the base is not using an outer join, so we add a new one for this class' tables.
            Map additionalExpMap = additionalTreatExpressionCriteriaMap();
            if (additionalExpMap!=null && !additionalExpMap.isEmpty()) {
                statement.addOuterJoinExpressionsHolders(additionalExpMap, parentDescriptor);
            }
        }
        typeExpression = typeExpression.normalize(normalizer);

        if (foreignKeyJoinPointer != null) {
            // If this expression is right side of an objExp.equal(objExp), one
            // need not add additionalExpressionCriteria twice.
            // Also the join will replace the original objExp.equal(objExp).
            // For CR#2456.
            foreignKeyJoinPointer.add(typeExpression.and(this.onClause));
        } else {
            //this just and's in the entire expression to the normalizer's expression.  Need to use this for TYPE and non-outerjoin components
            normalizer.addAdditionalLocalExpression(typeExpression.and(additionalTreatExpressionCriteria()).and(this.onClause));
        }
        return this;
    }
}
