/*
 * Copyright (c) 1998, 2020 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:
//     May 21, 2009-2.0 Chris Delahunt
//       - TODO Bug#: Bug Description
package org.eclipse.persistence.internal.expressions;

import java.io.BufferedWriter;
import java.io.IOException;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.expressions.ExpressionBuilder;
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.queries.ObjectLevelReadQuery;

/**
 * @author cdelahun
 *
 */
public class ClassTypeExpression extends DataExpression {

    /** Cache the aliased field. Only applies to attributes. */
    protected DatabaseField field;
    /** Cache the aliased field. Only applies to attributes. */
    protected DatabaseField aliasedField;

    /**
     *
     */
    public ClassTypeExpression(Expression base) {
        super();
        this.baseExpression = base;
    }

    public ClassTypeExpression() {
        super();
    }

    /**
     * INTERNAL:
     * Used for debug printing.
     */
    @Override
    public String descriptionOfNodeType() {
        return "Class For Inheritance";
    }

    /* (non-Javadoc)
     * @see org.eclipse.persistence.expressions.Expression#rebuildOn(org.eclipse.persistence.expressions.Expression)
     */
    @Override
    public Expression rebuildOn(Expression newBase) {
        Expression newLocalBase = getBaseExpression().rebuildOn(newBase);
        Expression result = newLocalBase.type();

        result.setSelectIfOrderedBy(selectIfOrderedBy());
        return result;
    }

    /**
     * INTERNAL
     * This method returns the inheritance field value for an object to conform in an in-memory query.
     * Similar to getFieldValue, but deals with an instance rather than a Class object directly
     */
    public Object typeValueFromObject(Object object, AbstractSession session) {
        // get the descriptor directly from the object, and use it to find the Java class
        ClassDescriptor objectDescriptor = session.getClassDescriptor(object);
        if (!objectDescriptor.hasInheritance()
                || objectDescriptor.getInheritancePolicy().shouldUseClassNameAsIndicator()
                || objectDescriptor.getInheritancePolicy().hasClassExtractor() ) {
            return (objectDescriptor.getJavaClassName());
        } else {
            return objectDescriptor.getInheritancePolicy().getClassIndicatorMapping().get(objectDescriptor.getJavaClass());
        }
    }

    @Override
    public void validateNode() {

        ClassDescriptor descriptor = getContainingDescriptor();
        if (descriptor ==null){
            throw QueryException.invalidTypeExpression(getBaseExpression());
        }
        if ( (!descriptor.hasInheritance()) || (!descriptor.getInheritancePolicy().hasClassIndicator()) ) {
            throw QueryException.invalidTypeExpression(descriptor.getJavaClassName());
        }
        super.validateNode();
    }

    /**
     * INTERNAL:
     * Return the value for in memory comparison.
     * This is only valid for value expressions.
     * Pulled from QueryKeyExpression valueFromObject
     */
    @Override
    public Object valueFromObject(Object object, AbstractSession session, AbstractRecord translationRow, int valueHolderPolicy, boolean isObjectUnregistered) {
        // The expression may be across a relationship, in which case it must be traversed.
        if ((!getBaseExpression().isExpressionBuilder()) && getBaseExpression().isQueryKeyExpression()) {
            object = getBaseExpression().valueFromObject(object, session, translationRow, valueHolderPolicy, isObjectUnregistered);

            // toDo: Null means the join filters out the row, returning null is not correct if an inner join,
            // outer/inner joins need to be fixed to filter correctly.
            if (object == null) {
                return null;
            }

            // If from an anyof the object will be a collection of values,
            // A new vector must union the object values and the values extracted from it.
            if (object instanceof Vector) {
                Vector comparisonVector = new Vector(((Vector)object).size() + 2);
                for (Enumeration valuesToIterate = ((Vector)object).elements();
                         valuesToIterate.hasMoreElements();) {
                    Object vectorObject = valuesToIterate.nextElement();
                    if (vectorObject == null) {
                        comparisonVector.addElement(null);
                    } else {
                        Object valueOrValues = typeValueFromObject(vectorObject, session);

                        // If a collection of values were extracted union them.
                        if (valueOrValues instanceof Vector) {
                            for (Enumeration nestedValuesToIterate = ((Vector)valueOrValues).elements();
                                     nestedValuesToIterate.hasMoreElements();) {
                                comparisonVector.addElement(nestedValuesToIterate.nextElement());
                            }
                        } else {
                            comparisonVector.addElement(valueOrValues);
                        }
                    }
                }
                return comparisonVector;
            }
        }
        return typeValueFromObject(object, session);
    }

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

    /**
     * INTERNAL:
     */
    @Override
    public DatabaseField getField() {
        if (field == null) {
            ClassDescriptor descriptor = getContainingDescriptor();

            if (!descriptor.hasInheritance() || descriptor.getInheritancePolicy().hasClassExtractor()){
                throw QueryException.invalidTypeExpression(descriptor.getJavaClassName());
            }
            field = descriptor.getInheritancePolicy().getClassIndicatorField();
        }
        return field;
    }

    /**
     * INTERNAL:
     * Transform the object-level value into a database-level value
     * objectValue is a Class or collection of Class objects and the returned value is the database representation
     * Example:  ObjectValue=LargeProject returns "L".
     */
    @Override
    public Object getFieldValue(Object objectValue, AbstractSession session) {
        if (objectValue ==null){
            return null;
        }

        if (objectValue instanceof Collection) {
                // This can actually be a collection for IN within expressions... however it would be better for expressions to handle this.
                Collection values = (Collection)objectValue;
                Vector fieldValues = new Vector(values.size());
                for (Iterator iterator = values.iterator(); iterator.hasNext();) {
                    Object value = iterator.next();
                    if (!(value instanceof Expression)){
                        value = getFieldValue(value, session);
                    }
                    fieldValues.add(value);
                }
                return fieldValues;
        } else {
            if (! (objectValue instanceof Class) ){
                throw QueryException.invalidTypeExpression(objectValue.getClass().toString());
            }

            ClassDescriptor descriptor = session.getDescriptor((Class)objectValue);
            if (descriptor == null){
                throw QueryException.invalidTypeExpression(objectValue.getClass().toString());
            }

            if (descriptor.hasInheritance() && !descriptor.getInheritancePolicy().shouldUseClassNameAsIndicator()){
                return descriptor.getInheritancePolicy().getClassIndicatorMapping().get(objectValue);
            } else {
                return ((Class)objectValue).getName();
            }
        }
    }

    /**
     * INTERNAL:
     * Like QueryKeyExpression, return the descriptor for the class type used, null if one can't be determined yet.
     * Should only be called when a session is already set.
     */
    @Override
    public ClassDescriptor getContainingDescriptor() {
        return ((ObjectExpression)getBaseExpression()).getDescriptor();

    }

    /**
     * INTERNAL:
     * Return the descriptor for the base expression.  This is used in ReportItem when building the
     * return value (a class), as none of the expressions will have a session.
     */
    public ClassDescriptor getContainingDescriptor(ObjectLevelReadQuery query) {
        Class queryClass = null;
        if (getBaseExpression().isExpressionBuilder()){
            queryClass = ((ExpressionBuilder)getBaseExpression()).getQueryClass();
            return query.getSession().getDescriptor(queryClass);
        } else {
            // It must be a QueryKeyExpression.
            return getBaseExpression().getLeafDescriptor(query, query.getDescriptor(), query.getSession());
        }
    }

    @Override
    public boolean isClassTypeExpression(){
        return true;
    }

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

    /**
     * INTERNAL:
     * For CR#2456 if this is part of an objExp.equal(objExp), do not need to add
     * additional expressions to normalizer both times, and the foreign key join
     * replaces the equal expression.
     */
    public Expression normalize(ExpressionNormalizer normalizer, Vector foreignKeyJoinPointer) {
        if (hasBeenNormalized()) {
            return this;
        }
        return super.normalize(normalizer);
    }

    /**
     * INTERNAL:
     * Alias the database field for our current environment
     */
    protected void initializeAliasedField() {
        DatabaseField tempField = getField().clone();
        DatabaseTable aliasedTable = getAliasedTable();

        aliasedField = tempField;
        aliasedField.setTable(aliasedTable);
    }

    /**
     * INTERNAL:
     * Return the field appropriately aliased
     */
    @Override
    public DatabaseField getAliasedField() {
        if (aliasedField == null) {
            initializeAliasedField();
        }
        return aliasedField;

    }

    /**
     * Return the alias for our table
     */
    protected DatabaseTable getAliasedTable() {
        DataExpression base = (DataExpression)getBaseExpression();

        DatabaseTable alias = base.aliasForTable(getField().getTable());
        if (alias == null) {
            return getField().getTable();
        } else {
            return alias;
        }
    }

    /**
     * INTERNAL:
     * Return all the fields
     */
    @Override
    public Vector getFields() {
        Vector result = new Vector(1);
        DatabaseField field = getField();
        if (field != null) {
            result.addElement(field);
        }
        return result;
    }

    @Override
    public Expression twistedForBaseAndContext(Expression newBase, Expression context, Expression oldBase) {
        if (oldBase == null || this.baseExpression == oldBase) {
            Expression twistedBase = this.baseExpression.twistedForBaseAndContext(newBase, context, oldBase);
            return twistedBase.type();
        }

        return this;
    }
}
