/*******************************************************************************
 * Copyright (c) 2006 Oracle Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Cameron Bateman/Oracle - initial API and implementation
 *    
 ********************************************************************************/

package org.eclipse.jst.jsf.validation.internal.el.operators;

import java.math.BigDecimal;
import java.math.BigInteger;

import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.jdt.core.IType;
import org.eclipse.jst.jsf.common.internal.types.BooleanLiteralType;
import org.eclipse.jst.jsf.common.internal.types.IAssignable;
import org.eclipse.jst.jsf.common.internal.types.LiteralType;
import org.eclipse.jst.jsf.common.internal.types.StringLiteralType;
import org.eclipse.jst.jsf.common.internal.types.TypeCoercer;
import org.eclipse.jst.jsf.common.internal.types.TypeCoercionException;
import org.eclipse.jst.jsf.common.internal.types.TypeConstants;
import org.eclipse.jst.jsf.common.internal.types.TypeTransformer;
import org.eclipse.jst.jsf.common.internal.types.ValueType;
import org.eclipse.jst.jsf.common.util.TypeUtil;
import org.eclipse.jst.jsf.context.symbol.internal.util.IObjectSymbolBasedValueType;
import org.eclipse.jst.jsf.validation.internal.el.diagnostics.DiagnosticFactory;

/**
 * A relational binary operator for equality: "==" or "!="
 * 
 * @author cbateman
 *
 */
/*package*/ abstract class EqualityRelationalBinaryOperator extends RelationalBinaryOperator 
{
    EqualityRelationalBinaryOperator(final DiagnosticFactory diagnosticFactory, String jsfVersion) 
    {
        super(diagnosticFactory, jsfVersion);
    }

    /**
     * @param firstArg
     * @param secondArg
     * @return the result of the operation
     */
    protected abstract boolean doRealOperation(Boolean firstArg, Boolean secondArg);

    /* (non-Javadoc)
     * @see org.eclipse.jst.jsf.validation.internal.el.operators.BinaryOperator#performOperation(org.eclipse.jst.jsf.core.internal.types.ValueType, org.eclipse.jst.jsf.core.internal.types.ValueType)
     */
    public ValueType performOperation(ValueType firstArg, ValueType secondArg) 
    {
        // JSP.2.3.5.7 step 2 if either operand is null, then not equal
        if (TypeCoercer.typeIsNull(firstArg.getSignature())
                || TypeCoercer.typeIsNull(secondArg.getSignature()))
        {
            return BooleanLiteralType.FALSE;
        }
        
        String boxedFirstType = TypeTransformer.transformBoxPrimitives(firstArg.getSignature());
        String boxedSecondType = TypeTransformer.transformBoxPrimitives(secondArg.getSignature());
        
        // JSP.2.3.5.7 step 3, if either is BigDecimal, promote both and compare
        if (TypeConstants.TYPE_BIG_DOUBLE.equals(boxedFirstType)
                || TypeConstants.TYPE_BIG_DOUBLE.equals(boxedSecondType))
        {
            return handleNumericComparison(firstArg, secondArg, BigDecimal.class);
        }
        
        // JSP.2.3.5.7, step 4 if either is a float or double, promote both to 
        // double and compare
        if (TypeConstants.TYPE_BOXED_DOUBLE.equals(boxedFirstType)
                || TypeConstants.TYPE_BOXED_FLOAT.equals(boxedFirstType)
                || TypeConstants.TYPE_BOXED_DOUBLE.equals(boxedSecondType)
                || TypeConstants.TYPE_BOXED_FLOAT.equals(boxedSecondType))
        {
            return handleNumericComparison(firstArg, secondArg, Double.class);
        }
        
        // JSP.2.3.5.7, step 5 if either is a big integer, promote and compare
        if (TypeConstants.TYPE_BIG_INTEGER.equals(boxedFirstType)
                || TypeConstants.TYPE_BIG_INTEGER.equals(boxedSecondType))
        {
            return handleNumericComparison(firstArg, secondArg, BigInteger.class);
        }
        
        // JSP.2.3.5.7, step 6 if either is Long or smaller, coerce both to Long
        if (TypeConstants.TYPE_BOXED_LONG.equals(boxedFirstType)
                || TypeConstants.TYPE_BOXED_LONG.equals(boxedSecondType)
                || TypeConstants.TYPE_BOXED_INTEGER.equals(boxedFirstType)
                || TypeConstants.TYPE_BOXED_INTEGER.equals(boxedSecondType)
                || TypeConstants.TYPE_BOXED_SHORT.equals(boxedFirstType)
                || TypeConstants.TYPE_BOXED_SHORT.equals(boxedSecondType)
                || TypeConstants.TYPE_BOXED_BYTE.equals(boxedFirstType)
                || TypeConstants.TYPE_BOXED_BYTE.equals(boxedSecondType)
                || TypeConstants.SIGNATURE_BOXED_CHARACTER.equals(boxedFirstType)
                || TypeConstants.SIGNATURE_BOXED_CHARACTER.equals(boxedSecondType))
        {
            return handleNumericComparison(firstArg, secondArg, Long.class);
        }
        
        // JSP.2.3.5.7, step 7 if either is a boolean, coerce to boolean
        if (TypeConstants.TYPE_BOXED_BOOLEAN.equals(boxedFirstType)
                || TypeConstants.TYPE_BOXED_BOOLEAN.equals(boxedSecondType))
        {
            return handleBooleanComparison(firstArg, secondArg);
        }
        
        // Unified EL 1.8.2, step 8 if either is a enum, then coerce both to enum
        // NOTE: we handle the JSF 1.1 case also where enums are treated as non-coercable
        // Object's
        if (firstArg.isEnumType() || secondArg.isEnumType())
        {
            return handleEnumComparison(firstArg, secondArg);
        }
        
        // JSP.2.3.5.7, step 8 if either is a string, coerce to string and
        // compare lexically
        if (TypeConstants.TYPE_STRING.equals(boxedFirstType)
                || TypeConstants.TYPE_STRING.equals(boxedSecondType))
        {
            return handleStringComparison(firstArg, secondArg);
        }
        
        // otherwise, an equal compare will be done A.equals(B).  Since 
        return new ValueType(TypeConstants.TYPE_BOOLEAN, IAssignable.ASSIGNMENT_TYPE_RHS);        
    }

    private ValueType handleEnumComparison(ValueType firstArg,
            ValueType secondArg) 
    {
        assert firstArg.isEnumType() || secondArg.isEnumType();
        
        // if the first is not an enum, then we have non-Enum == Enum case
        if (!firstArg.isEnumType())
        {
            return handleComparsionOfEnumAndNonEnum(secondArg, firstArg);
        }
        
        // if the second is not an enum, then we have Enum == non-Enum case
        if (!secondArg.isEnumType())
        {
            return handleComparsionOfEnumAndNonEnum(firstArg, secondArg);
        }
        
        // only other case is they are both enums.  Check if they are directly
        // comparable.
        if (TypeUtil.canNeverBeEqual(firstArg.getSignature(), secondArg.getSignature()))
        {
            boolean result = doRealOperation("foo", "notFoo");  // just simulate the operation where the operands are not equal //$NON-NLS-1$ //$NON-NLS-2$
            
            return BooleanLiteralType.valueOf(result);
        }
        
        // otherwise, all we know is that it's a boolean
        return new ValueType(TypeConstants.TYPE_BOOLEAN, IAssignable.ASSIGNMENT_TYPE_RHS);
    }

    private ValueType handleComparsionOfEnumAndNonEnum(ValueType enumType,
            ValueType nonEnumType) 
    {
        // the only literal value that could have got us here is a 
        // StringLiteralValue since the others a filtered out before this is
        // called
        if (nonEnumType instanceof LiteralType)
        {
            assert nonEnumType instanceof StringLiteralType;
            
            Diagnostic result = validateIfEnumToStringComparison(((StringLiteralType)nonEnumType).getLiteralValue(), enumType);
            
            if (result != null)
            {
                // compare two things that aren't equal
                return BooleanLiteralType.valueOf(doRealOperation("foo", "foo_")); //$NON-NLS-1$ //$NON-NLS-2$
            }
            return new ValueType(TypeConstants.TYPE_BOOLEAN, IAssignable.ASSIGNMENT_TYPE_RHS);
        }
        
        // if the arg is a String, then we can't prove anything before runtime
        if (nonEnumType.isInstanceOf(TypeConstants.TYPE_STRING))
        {
            return new ValueType(TypeConstants.TYPE_BOOLEAN, IAssignable.ASSIGNMENT_TYPE_RHS);
        }
        // otherwise, we know it will result in a problem since one is an enum
        // and the other isn't so simply do a comparison on two things that aren't equals
        return BooleanLiteralType.valueOf(doRealOperation("foo", "foo_")); //$NON-NLS-1$ //$NON-NLS-2$
    }

    public Diagnostic validate(ValueType firstArg, ValueType secondArg) {
        
        // JSP.2.3.5.7 step 2 if either operand is null, then not equal
        if (TypeCoercer.typeIsNull(firstArg.getSignature())
                || TypeCoercer.typeIsNull(secondArg.getSignature()))
        {
            // TODO: this is a strange thing to do...
            final boolean result = doRealOperation(Integer.valueOf(4), null);
            return _diagnosticFactory.create_BINARY_OP_EQUALITY_COMP_WITH_NULL_ALWAYS_EVAL_SAME(Boolean.toString(result));
        }

        final String boxedFirstType = 
            TypeTransformer.transformBoxPrimitives(firstArg.getSignature());
        final String boxedSecondType = 
            TypeTransformer.transformBoxPrimitives(secondArg.getSignature());
        
        // JSP.2.3.5.7 step 3, if either is BigDecimal, promote both and compare
        if (TypeConstants.TYPE_BIG_DOUBLE.equals(boxedFirstType)
                || TypeConstants.TYPE_BIG_DOUBLE.equals(boxedSecondType))
        {
            return validateNumericComparison(firstArg, secondArg, BigDecimal.class);
        }
        
        // JSP.2.3.5.7, step 4 if either is a float or double, promote both to 
        // double and compare
        if (TypeConstants.TYPE_BOXED_DOUBLE.equals(boxedFirstType)
                || TypeConstants.TYPE_BOXED_FLOAT.equals(boxedFirstType)
                || TypeConstants.TYPE_BOXED_DOUBLE.equals(boxedSecondType)
                || TypeConstants.TYPE_BOXED_FLOAT.equals(boxedSecondType))
        {
            return validateNumericComparison(firstArg, secondArg, Double.class);
        }
        
        // JSP.2.3.5.7, step 5 if either is a big integer, promote and compare
        if (TypeConstants.TYPE_BIG_INTEGER.equals(boxedFirstType)
                || TypeConstants.TYPE_BIG_INTEGER.equals(boxedSecondType))
        {
            return validateNumericComparison(firstArg, secondArg, BigInteger.class);
        }
        
        // JSP.2.3.5.7, step 6 if either is Long or smaller, coerce both to Long
        if (TypeConstants.TYPE_BOXED_LONG.equals(boxedFirstType)
                || TypeConstants.TYPE_BOXED_LONG.equals(boxedSecondType)
                || TypeConstants.TYPE_BOXED_INTEGER.equals(boxedFirstType)
                || TypeConstants.TYPE_BOXED_INTEGER.equals(boxedSecondType)
                || TypeConstants.TYPE_BOXED_SHORT.equals(boxedFirstType)
                || TypeConstants.TYPE_BOXED_SHORT.equals(boxedSecondType)
                || TypeConstants.TYPE_BOXED_BYTE.equals(boxedFirstType)
                || TypeConstants.TYPE_BOXED_BYTE.equals(boxedSecondType)
                || TypeConstants.SIGNATURE_BOXED_CHARACTER.equals(boxedFirstType)
                || TypeConstants.SIGNATURE_BOXED_CHARACTER.equals(boxedSecondType))
        {
            return validateNumericComparison(firstArg, secondArg, Long.class);
        }
        
        // JSP.2.3.5.7, step 7 if either is a boolean, coerce to boolean
        if (TypeConstants.TYPE_BOXED_BOOLEAN.equals(boxedFirstType)
                || TypeConstants.TYPE_BOXED_BOOLEAN.equals(boxedSecondType))
        {
            return validateBooleanComparison(firstArg, secondArg);
        }
        
        // Unified EL 1.8.2, step 8 if either is a enum, then coerce both to enum
        // NOTE: we handle the JSF 1.1 case also where enums are treated as non-coercable
        // Object's
        if (firstArg.isEnumType() || secondArg.isEnumType())
        {
            return validateEnumComparison(firstArg, secondArg);
        }
        
        // JSP.2.3.5.7, step 8 if either is a string, coerce to string and
        // compare lexically
        if (TypeConstants.TYPE_STRING.equals(boxedFirstType)
                || TypeConstants.TYPE_STRING.equals(boxedSecondType))
        {
            return validateStringComparison(firstArg, secondArg);
        }

        // otherwise, an equal compare will be done A.equals(B).  Since 
        return Diagnostic.OK_INSTANCE;
    }

    
    /**
     * Both types are coerced to boolean before comparison
     * 
     * @param firstArg
     * @param secondArg
     * @return the result of the comparison
     */
    private ValueType handleBooleanComparison(ValueType firstArg, ValueType secondArg)
    {
        boolean canCoerceFirstArg =  
            TypeCoercer.canCoerceToBoolean(TypeTransformer.transformBoxPrimitives(firstArg.getSignature()));
        boolean canCoerceSecondArg = TypeCoercer.canCoerceToBoolean(TypeTransformer.transformBoxPrimitives(secondArg.getSignature()));

        if (! (canCoerceFirstArg && canCoerceSecondArg))
        {
            return null;
        }
        
        if (firstArg instanceof LiteralType && secondArg instanceof LiteralType)
        {
            try
            {
                Boolean firstValue = ((LiteralType)firstArg).coerceToBoolean();
                Boolean secondValue = ((LiteralType)secondArg).coerceToBoolean();
                
                if (firstValue != null && secondValue != null)
                {
                    boolean result = doRealOperation(firstValue, secondValue);
                    return result ? 
                               BooleanLiteralType.TRUE : 
                                       BooleanLiteralType.FALSE;
                }
            }
            catch (TypeCoercionException tce)
            {
                throw new AssertionError("should never get here; have already checked coercability above"); //$NON-NLS-1$
            }
        }
        
        // otherwise, we have a valid comparison that results in boolean
        return new ValueType(TypeConstants.TYPE_BOOLEAN, IAssignable.ASSIGNMENT_TYPE_RHS);
    }
    
    private Diagnostic validateBooleanComparison(ValueType firstType, ValueType secondType)
    {
        boolean canCoerceFirstArg =  
            TypeCoercer.canCoerceToBoolean(TypeTransformer.transformBoxPrimitives(firstType.getSignature()));
        boolean canCoerceSecondArg = TypeCoercer.canCoerceToBoolean(TypeTransformer.transformBoxPrimitives(secondType.getSignature()));

        if (!canCoerceFirstArg)
        {
            return _diagnosticFactory.create_BINARY_OP_CANNOT_COERCE_ARGUMENT_TO_BOOLEAN(Messages.getString("EqualityRelationalBinaryOperator.FirstArgument")); //$NON-NLS-1$
        }
        
        if (!canCoerceSecondArg)
        {
            return _diagnosticFactory.create_BINARY_OP_CANNOT_COERCE_ARGUMENT_TO_BOOLEAN(Messages.getString("EqualityRelationalBinaryOperator.SecondArgument")); //$NON-NLS-1$
        }
        
        if (firstType instanceof LiteralType && secondType instanceof LiteralType)
        {
            try
            {
                Boolean firstValue = ((LiteralType)firstType).coerceToBoolean();
                Boolean secondValue = ((LiteralType)secondType).coerceToBoolean();
                
                if (firstValue != null && secondValue != null)
                {
                    final boolean result = 
                        doRealOperation(firstValue, secondValue);
                    return _diagnosticFactory.
                        create_BINARY_OP_CONSTANT_EXPRESSION_ALWAYS_EVAL_SAME(getOperationName(), Boolean.toString(result));
                }
            }
            catch (TypeCoercionException tce)
            {
                throw new AssertionError("should never get here; have already checked coercability above"); //$NON-NLS-1$
            }
        }
        
        // otherwise, we have a valid comparison
        return Diagnostic.OK_INSTANCE;
    }
    
    @Override
    protected Diagnostic validateStringComparison(ValueType firstType,
            ValueType secondType) 
    {
        String firstValue = null;

        if (firstType instanceof LiteralType)
        {
            firstValue = ((LiteralType)firstType).getLiteralValue();
        }

        String secondValue = null;
        if (secondType instanceof LiteralType)
        {
            secondValue = ((LiteralType)secondType).getLiteralValue();
        }

        if (firstValue != null)
        { 
            Diagnostic result = validateIfEnumToStringComparison(firstValue, secondType);
            
            if (result != null)
            {
                return result;
            }
        }

        if (secondValue != null)
        {
            Diagnostic result = validateIfEnumToStringComparison(secondValue, firstType);
            
            if (result != null)
            {
                return result;
            }
        }
        
        // if it's a string to enum compare, do the default parent thing
        return super.validateStringComparison(firstType, secondType);
    }

    
    @Override
    protected ValueType handleStringComparison(ValueType firstType,
            ValueType secondType) 
    {
        String firstValue = null;

        if (firstType instanceof LiteralType)
        {
            firstValue = ((LiteralType)firstType).getLiteralValue();
        }

        String secondValue = null;
        if (secondType instanceof LiteralType)
        {
            secondValue = ((LiteralType)secondType).getLiteralValue();
        }

        if (firstValue != null)
        { 
            Diagnostic result = validateIfEnumToStringComparison(firstValue, secondType);
            
            if (result != null)
            {
                return handleIfEnumToNonMemberStringComparison(firstValue, secondType);
            }
        }

        if (secondValue != null)
        {
            Diagnostic result = validateIfEnumToStringComparison(secondValue, firstType);
            
            if (result != null)
            {
                return handleIfEnumToNonMemberStringComparison(secondValue, firstType);
            }
        }

        // otherwise, do the super thing
        return super.handleStringComparison(firstType, secondType);
    }

    private Diagnostic validateEnumComparison(final ValueType firstArg, final ValueType secondArg)
    {
        assert firstArg.isEnumType() || secondArg.isEnumType();
        
        // if the first is not an enum, then we have non-Enum == Enum case
        if (!firstArg.isEnumType())
        {
            return validateComparsionOfEnumAndNonEnum(firstArg, secondArg);
        }
        
        // if the second is not an enum, then we have Enum == non-Enum case
        if (!secondArg.isEnumType())
        {
            return validateComparsionOfEnumAndNonEnum(secondArg, firstArg);
        }
        
        // only other case is they are both enums.  Check if they are directly
        // comparable.
        if (TypeUtil.canNeverBeEqual(firstArg.getSignature(), secondArg.getSignature()))
        {
            return _diagnosticFactory.
                create_BINARY_COMPARISON_WITH_TWO_ENUMS_ALWAYS_SAME
                    (getOperationName()
                     , doRealOperation("foo", "notFoo")  // just simulate the operation where the operands are not equal //$NON-NLS-1$ //$NON-NLS-2$
                     , TypeUtil.getFullyQualifiedName(firstArg.getSignature())
                     , TypeUtil.getFullyQualifiedName(secondArg.getSignature())); 
        }
        
        // otherwise, it's all good
        return Diagnostic.OK_INSTANCE;
    }
    
    private Diagnostic validateComparsionOfEnumAndNonEnum(final ValueType nonEnumType, final ValueType enumType)
    {
        // the only literal value that could have got us here is a 
        // StringLiteralValue since the others a filtered out before this is
        // called
        if (nonEnumType instanceof LiteralType)
        {
            assert nonEnumType instanceof StringLiteralType;
            
            Diagnostic result = validateIfEnumToStringComparison(((StringLiteralType)nonEnumType).getLiteralValue(), enumType);
            
            if (result != null)
            {
                return result;
            }
            return Diagnostic.OK_INSTANCE;
        }
        
        // if the arg is a String, then we can't prove anything before runtime
        if (nonEnumType.isInstanceOf(TypeConstants.TYPE_STRING))
        {
            return Diagnostic.OK_INSTANCE;
        }
        // otherwise, we know it will result in a problem since one is an enum
        // and the other isn't
        return _diagnosticFactory.
            create_BINARY_COMPARISON_WITH_ENUM_AND_UNCOERCABLE_NONCONST_ALWAYS_SAME
                (getOperationName()
                 , doRealOperation("foo", "notFoo")  // just simulate the operation where the operands are not equal //$NON-NLS-1$ //$NON-NLS-2$
                 , TypeUtil.getFullyQualifiedName(enumType.getSignature())
                 , TypeUtil.getFullyQualifiedName(nonEnumType.getSignature())); 
    }
    
    private Diagnostic validateIfEnumToStringComparison(final String literalValue, final ValueType validateIfEnum)
    {
        if (validateIfEnum.isEnumType()
                && validateIfEnum instanceof IObjectSymbolBasedValueType)
        {
            final IObjectSymbolBasedValueType symbolValueType =
                (IObjectSymbolBasedValueType) validateIfEnum;
            
            IType type = symbolValueType.getSymbol().getTypeDescriptor().resolveType(symbolValueType.getSymbol().getTypeDescriptor().getTypeSignature());
            
            if (type != null && !TypeUtil.isEnumMember(type, literalValue))
            {
                return _diagnosticFactory.
                    create_BINARY_COMPARISON_WITH_ENUM_AND_CONST_ALWAYS_SAME
                        (getOperationName()
                         , doRealOperation(literalValue, literalValue+"_")  // just simulate the operation where the operands are not equal //$NON-NLS-1$
                         , TypeUtil.getFullyQualifiedName(validateIfEnum.getSignature())
                         , literalValue);
            }
        }
       
        return null;
    }
    
    private ValueType handleIfEnumToNonMemberStringComparison(final String literalValue, final ValueType enumValueType)
    {
        // we need to apply the real operation to literalValue and any string that !equals(literalValue)
        // since it's not a member of the enum
        return BooleanLiteralType.valueOf(doRealOperation(literalValue, literalValue+"_")); //$NON-NLS-1$
    }
}
