/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.el.lang;

import java.beans.PropertyEditor;
import java.beans.PropertyEditorManager;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collections;
import java.util.Map;
import java.util.Set;

import javax.el.ELContext;
import javax.el.ELException;

import org.apache.el.util.MessageFactory;


/**
 * A helper class that implements the EL Specification
 *
 * @author Jacob Hookom [jacob@hookom.net]
 */
public class ELSupport {

    private static final Long ZERO = Long.valueOf(0L);

    protected static final boolean COERCE_TO_ZERO;

    static {
        String coerceToZeroStr;
        if (System.getSecurityManager() != null) {
            coerceToZeroStr = AccessController.doPrivileged(
                    new PrivilegedAction<String>(){
                        @Override
                        public String run() {
                            return System.getProperty(
                                    "org.apache.el.parser.COERCE_TO_ZERO", "false");
                        }
                    }
            );
        } else {
            coerceToZeroStr = System.getProperty(
                    "org.apache.el.parser.COERCE_TO_ZERO", "false");
        }
        COERCE_TO_ZERO = Boolean.parseBoolean(coerceToZeroStr);
    }


    /**
     * Compare two objects, after coercing to the same type if appropriate.
     *
     * If the objects are identical, or they are equal according to
     * {@link #equals(ELContext, Object, Object)} then return 0.
     *
     * If either object is a BigDecimal, then coerce both to BigDecimal first.
     * Similarly for Double(Float), BigInteger, and Long(Integer, Char, Short, Byte).
     *
     * Otherwise, check that the first object is an instance of Comparable, and compare
     * against the second object. If that is null, return 1, otherwise
     * return the result of comparing against the second object.
     *
     * Similarly, if the second object is Comparable, if the first is null, return -1,
     * else return the result of comparing against the first object.
     *
     * A null object is considered as:
     * <ul>
     * <li>ZERO when compared with Numbers</li>
     * <li>the empty string for String compares</li>
     * <li>Otherwise null is considered to be lower than anything else.</li>
     * </ul>
     *
     * @param ctx the context in which this comparison is taking place
     * @param obj0 first object
     * @param obj1 second object
     * @return -1, 0, or 1 if this object is less than, equal to, or greater than val.
     * @throws ELException if neither object is Comparable
     * @throws ClassCastException if the objects are not mutually comparable
     */
    public static final int compare(final ELContext ctx, final Object obj0, final Object obj1)
            throws ELException {
        if (obj0 == obj1 || equals(ctx, obj0, obj1)) {
            return 0;
        }
        if (isBigDecimalOp(obj0, obj1)) {
            BigDecimal bd0 = (BigDecimal) coerceToNumber(ctx, obj0, BigDecimal.class);
            BigDecimal bd1 = (BigDecimal) coerceToNumber(ctx, obj1, BigDecimal.class);
            return bd0.compareTo(bd1);
        }
        if (isDoubleOp(obj0, obj1)) {
            Double d0 = (Double) coerceToNumber(ctx, obj0, Double.class);
            Double d1 = (Double) coerceToNumber(ctx, obj1, Double.class);
            return d0.compareTo(d1);
        }
        if (isBigIntegerOp(obj0, obj1)) {
            BigInteger bi0 = (BigInteger) coerceToNumber(ctx, obj0, BigInteger.class);
            BigInteger bi1 = (BigInteger) coerceToNumber(ctx, obj1, BigInteger.class);
            return bi0.compareTo(bi1);
        }
        if (isLongOp(obj0, obj1)) {
            Long l0 = (Long) coerceToNumber(ctx, obj0, Long.class);
            Long l1 = (Long) coerceToNumber(ctx, obj1, Long.class);
            return l0.compareTo(l1);
        }
        if (obj0 instanceof String || obj1 instanceof String) {
            return coerceToString(ctx, obj0).compareTo(coerceToString(ctx, obj1));
        }
        if (obj0 instanceof Comparable<?>) {
            @SuppressWarnings("unchecked") // checked above
            final Comparable<Object> comparable = (Comparable<Object>) obj0;
            return (obj1 != null) ? comparable.compareTo(obj1) : 1;
        }
        if (obj1 instanceof Comparable<?>) {
            @SuppressWarnings("unchecked") // checked above
            final Comparable<Object> comparable = (Comparable<Object>) obj1;
            return (obj0 != null) ? -comparable.compareTo(obj0) : -1;
        }
        throw new ELException(MessageFactory.get("error.compare", obj0, obj1));
    }

    /**
     * Compare two objects for equality, after coercing to the same type if appropriate.
     *
     * If the objects are identical (including both null) return true.
     * If either object is null, return false.
     * If either object is Boolean, coerce both to Boolean and check equality.
     * Similarly for Enum, String, BigDecimal, Double(Float), Long(Integer, Short, Byte, Character)
     * Otherwise default to using Object.equals().
     *
     * @param ctx the context in which this equality test is taking place
     * @param obj0 the first object
     * @param obj1 the second object
     * @return true if the objects are equal
     * @throws ELException if one of the coercion fails
     */
    public static final boolean equals(final ELContext ctx, final Object obj0, final Object obj1)
            throws ELException {
        if (obj0 == obj1) {
            return true;
        } else if (obj0 == null || obj1 == null) {
            return false;
        } else if (isBigDecimalOp(obj0, obj1)) {
            BigDecimal bd0 = (BigDecimal) coerceToNumber(ctx, obj0, BigDecimal.class);
            BigDecimal bd1 = (BigDecimal) coerceToNumber(ctx, obj1, BigDecimal.class);
            return bd0.equals(bd1);
        } else if (isDoubleOp(obj0, obj1)) {
            Double d0 = (Double) coerceToNumber(ctx, obj0, Double.class);
            Double d1 = (Double) coerceToNumber(ctx, obj1, Double.class);
            return d0.equals(d1);
        } else if (isBigIntegerOp(obj0, obj1)) {
            BigInteger bi0 = (BigInteger) coerceToNumber(ctx, obj0, BigInteger.class);
            BigInteger bi1 = (BigInteger) coerceToNumber(ctx, obj1, BigInteger.class);
            return bi0.equals(bi1);
        } else         if (isLongOp(obj0, obj1)) {
            Long l0 = (Long) coerceToNumber(ctx, obj0, Long.class);
            Long l1 = (Long) coerceToNumber(ctx, obj1, Long.class);
            return l0.equals(l1);
        } else if (obj0 instanceof Boolean || obj1 instanceof Boolean) {
            return coerceToBoolean(ctx, obj0, false).equals(coerceToBoolean(ctx, obj1, false));
        } else if (obj0.getClass().isEnum()) {
            return obj0.equals(coerceToEnum(ctx, obj1, obj0.getClass()));
        } else if (obj1.getClass().isEnum()) {
            return obj1.equals(coerceToEnum(ctx, obj0, obj1.getClass()));
        } else if (obj0 instanceof String || obj1 instanceof String) {
            int lexCompare = coerceToString(ctx, obj0).compareTo(coerceToString(ctx, obj1));
            return (lexCompare == 0) ? true : false;
        } else {
            return obj0.equals(obj1);
        }
    }

    // Going to have to have some casts /raw types somewhere so doing it here
    // keeps them all in one place. There might be a neater / better solution
    // but I couldn't find it
    @SuppressWarnings("unchecked")
    public static final Enum<?> coerceToEnum(final ELContext ctx, final Object obj,
            @SuppressWarnings("rawtypes") Class type) {

        if (ctx != null) {
            boolean originalIsPropertyResolved = ctx.isPropertyResolved();
            try {
                Object result = ctx.getELResolver().convertToType(ctx, obj, type);
                if (ctx.isPropertyResolved()) {
                    return (Enum<?>) result;
                }
            } finally {
                ctx.setPropertyResolved(originalIsPropertyResolved);
            }
        }

        if (obj == null || "".equals(obj)) {
            return null;
        }
        if (type.isAssignableFrom(obj.getClass())) {
            return (Enum<?>) obj;
        }

        if (!(obj instanceof String)) {
            throw new ELException(MessageFactory.get("error.convert",
                    obj, obj.getClass(), type));
        }

        Enum<?> result;
        try {
             result = Enum.valueOf(type, (String) obj);
        } catch (IllegalArgumentException iae) {
            throw new ELException(MessageFactory.get("error.convert",
                    obj, obj.getClass(), type));
        }
        return result;
    }

    /**
     * Convert an object to Boolean.
     * Null and empty string are false.
     * @param ctx the context in which this conversion is taking place
     * @param obj the object to convert
     * @param primitive is the target a primitive in which case coercion to null
     *                  is not permitted
     * @return the Boolean value of the object
     * @throws ELException if object is not Boolean or String
     */
    public static final Boolean coerceToBoolean(final ELContext ctx, final Object obj,
            boolean primitive) throws ELException {

        if (ctx != null) {
            boolean originalIsPropertyResolved = ctx.isPropertyResolved();
            try {
                Object result = ctx.getELResolver().convertToType(ctx, obj, Boolean.class);
                if (ctx.isPropertyResolved()) {
                    return (Boolean) result;
                }
            } finally {
                ctx.setPropertyResolved(originalIsPropertyResolved);
            }
        }

        if (!COERCE_TO_ZERO && !primitive) {
            if (obj == null) {
                return null;
            }
        }

        if (obj == null || "".equals(obj)) {
            return Boolean.FALSE;
        }
        if (obj instanceof Boolean) {
            return (Boolean) obj;
        }
        if (obj instanceof String) {
            return Boolean.valueOf((String) obj);
        }

        throw new ELException(MessageFactory.get("error.convert",
                obj, obj.getClass(), Boolean.class));
    }

    private static final Character coerceToCharacter(final ELContext ctx, final Object obj)
            throws ELException {

        if (ctx != null) {
            boolean originalIsPropertyResolved = ctx.isPropertyResolved();
            try {
                Object result = ctx.getELResolver().convertToType(ctx, obj, Character.class);
                if (ctx.isPropertyResolved()) {
                    return (Character) result;
                }
            } finally {
                ctx.setPropertyResolved(originalIsPropertyResolved);
            }
        }

        if (obj == null || "".equals(obj)) {
            return Character.valueOf((char) 0);
        }
        if (obj instanceof String) {
            return Character.valueOf(((String) obj).charAt(0));
        }
        if (ELArithmetic.isNumber(obj)) {
            return Character.valueOf((char) ((Number) obj).shortValue());
        }
        Class<?> objType = obj.getClass();
        if (obj instanceof Character) {
            return (Character) obj;
        }

        throw new ELException(MessageFactory.get("error.convert",
                obj, objType, Character.class));
    }

    protected static final Number coerceToNumber(final Number number,
            final Class<?> type) throws ELException {
        if (Long.TYPE == type || Long.class.equals(type)) {
            return Long.valueOf(number.longValue());
        }
        if (Double.TYPE == type || Double.class.equals(type)) {
            return Double.valueOf(number.doubleValue());
        }
        if (Integer.TYPE == type || Integer.class.equals(type)) {
            return Integer.valueOf(number.intValue());
        }
        if (BigInteger.class.equals(type)) {
            if (number instanceof BigDecimal) {
                return ((BigDecimal) number).toBigInteger();
            }
            if (number instanceof BigInteger) {
                return number;
            }
            return BigInteger.valueOf(number.longValue());
        }
        if (BigDecimal.class.equals(type)) {
            if (number instanceof BigDecimal) {
                return number;
            }
            if (number instanceof BigInteger) {
                return new BigDecimal((BigInteger) number);
            }
            return new BigDecimal(number.doubleValue());
        }
        if (Byte.TYPE == type || Byte.class.equals(type)) {
            return Byte.valueOf(number.byteValue());
        }
        if (Short.TYPE == type || Short.class.equals(type)) {
            return Short.valueOf(number.shortValue());
        }
        if (Float.TYPE == type || Float.class.equals(type)) {
            return Float.valueOf(number.floatValue());
        }
        if (Number.class.equals(type)) {
            return number;
        }

        throw new ELException(MessageFactory.get("error.convert",
                number, number.getClass(), type));
    }

    public static final Number coerceToNumber(final ELContext ctx, final Object obj,
            final Class<?> type) throws ELException {

        if (ctx != null) {
            boolean originalIsPropertyResolved = ctx.isPropertyResolved();
            try {
                Object result = ctx.getELResolver().convertToType(ctx, obj, type);
                if (ctx.isPropertyResolved()) {
                    return (Number) result;
                }
            } finally {
                ctx.setPropertyResolved(originalIsPropertyResolved);
            }
        }

        if (!COERCE_TO_ZERO) {
            if (obj == null && !type.isPrimitive()) {
                return null;
            }
        }

        if (obj == null || "".equals(obj)) {
            return coerceToNumber(ZERO, type);
        }
        if (obj instanceof String) {
            return coerceToNumber((String) obj, type);
        }
        if (ELArithmetic.isNumber(obj)) {
            return coerceToNumber((Number) obj, type);
        }

        if (obj instanceof Character) {
            return coerceToNumber(Short.valueOf((short) ((Character) obj)
                    .charValue()), type);
        }

        throw new ELException(MessageFactory.get("error.convert",
                obj, obj.getClass(), type));
    }

    protected static final Number coerceToNumber(final String val,
            final Class<?> type) throws ELException {
        if (Long.TYPE == type || Long.class.equals(type)) {
            try {
                return Long.valueOf(val);
            } catch (NumberFormatException nfe) {
                throw new ELException(MessageFactory.get("error.convert",
                        val, String.class, type));
            }
        }
        if (Integer.TYPE == type || Integer.class.equals(type)) {
            try {
                return Integer.valueOf(val);
            } catch (NumberFormatException nfe) {
                throw new ELException(MessageFactory.get("error.convert",
                        val, String.class, type));
            }
        }
        if (Double.TYPE == type || Double.class.equals(type)) {
            try {
                return Double.valueOf(val);
            } catch (NumberFormatException nfe) {
                throw new ELException(MessageFactory.get("error.convert",
                        val, String.class, type));
            }
        }
        if (BigInteger.class.equals(type)) {
            try {
                return new BigInteger(val);
            } catch (NumberFormatException nfe) {
                throw new ELException(MessageFactory.get("error.convert",
                        val, String.class, type));
            }
        }
        if (BigDecimal.class.equals(type)) {
            try {
                return new BigDecimal(val);
            } catch (NumberFormatException nfe) {
                throw new ELException(MessageFactory.get("error.convert",
                        val, String.class, type));
            }
        }
        if (Byte.TYPE == type || Byte.class.equals(type)) {
            try {
                return Byte.valueOf(val);
            } catch (NumberFormatException nfe) {
                throw new ELException(MessageFactory.get("error.convert",
                        val, String.class, type));
            }
        }
        if (Short.TYPE == type || Short.class.equals(type)) {
            try {
                return Short.valueOf(val);
            } catch (NumberFormatException nfe) {
                throw new ELException(MessageFactory.get("error.convert",
                        val, String.class, type));
            }
        }
        if (Float.TYPE == type || Float.class.equals(type)) {
            try {
                return Float.valueOf(val);
            } catch (NumberFormatException nfe) {
                throw new ELException(MessageFactory.get("error.convert",
                        val, String.class, type));
            }
        }

        throw new ELException(MessageFactory.get("error.convert",
                val, String.class, type));
    }

    /**
     * Coerce an object to a string.
     * @param ctx the context in which this conversion is taking place
     * @param obj the object to convert
     * @return the String value of the object
     */
    public static final String coerceToString(final ELContext ctx, final Object obj) {

        if (ctx != null) {
            boolean originalIsPropertyResolved = ctx.isPropertyResolved();
            try {
                Object result = ctx.getELResolver().convertToType(ctx, obj, String.class);
                if (ctx.isPropertyResolved()) {
                    return (String) result;
                }
            } finally {
                ctx.setPropertyResolved(originalIsPropertyResolved);
            }
        }

        if (obj == null) {
            return "";
        } else if (obj instanceof String) {
            return (String) obj;
        } else if (obj instanceof Enum<?>) {
            return ((Enum<?>) obj).name();
        } else {
            return obj.toString();
        }
    }

    public static final Object coerceToType(final ELContext ctx, final Object obj,
            final Class<?> type) throws ELException {

        if (ctx != null) {
            boolean originalIsPropertyResolved = ctx.isPropertyResolved();
            try {
                Object result = ctx.getELResolver().convertToType(ctx, obj, type);
                if (ctx.isPropertyResolved()) {
                    return result;
                }
            } finally {
                ctx.setPropertyResolved(originalIsPropertyResolved);
            }
        }

        if (type == null || Object.class.equals(type) ||
                (obj != null && type.isAssignableFrom(obj.getClass()))) {
            return obj;
        }

        if (!COERCE_TO_ZERO) {
            if (obj == null && !type.isPrimitive() &&
                    !String.class.isAssignableFrom(type)) {
                return null;
            }
        }

        if (String.class.equals(type)) {
            return coerceToString(ctx, obj);
        }
        if (ELArithmetic.isNumberType(type)) {
            return coerceToNumber(ctx, obj, type);
        }
        if (Character.class.equals(type) || Character.TYPE == type) {
            return coerceToCharacter(ctx, obj);
        }
        if (Boolean.class.equals(type) || Boolean.TYPE == type) {
            return coerceToBoolean(ctx, obj, Boolean.TYPE == type);
        }
        if (type.isEnum()) {
            return coerceToEnum(ctx, obj, type);
        }

        // new to spec
        if (obj == null)
            return null;
        if (obj instanceof String) {
            PropertyEditor editor = PropertyEditorManager.findEditor(type);
            if (editor == null) {
                if ("".equals(obj)) {
                    return null;
                }
                throw new ELException(MessageFactory.get("error.convert", obj,
                        obj.getClass(), type));
            } else {
                try {
                    editor.setAsText((String) obj);
                    return editor.getValue();
                } catch (RuntimeException e) {
                    if ("".equals(obj)) {
                        return null;
                    }
                    throw new ELException(MessageFactory.get("error.convert",
                            obj, obj.getClass(), type), e);
                }
            }
        }

        // Handle special case because the syntax for the empty set is the same
        // for an empty map. The parser will always parse {} as an empty set.
        if (obj instanceof Set && type == Map.class &&
                ((Set<?>) obj).isEmpty()) {
            return Collections.EMPTY_MAP;
        }

        // Handle arrays
        if (type.isArray() && obj.getClass().isArray()) {
            return coerceToArray(ctx, obj, type);
        }

        throw new ELException(MessageFactory.get("error.convert",
                obj, obj.getClass(), type));
    }

    private static Object coerceToArray(final ELContext ctx, final Object obj,
            final Class<?> type) {
        // Note: Nested arrays will result in nested calls to this method.

        // Note: Calling method has checked the obj is an array.

        int size = Array.getLength(obj);
        // Cast the input object to an array (calling method has checked it is
        // an array)
        // Get the target type for the array elements
        Class<?> componentType = type.getComponentType();
        // Create a new array of the correct type
        Object result = Array.newInstance(componentType, size);
        // Coerce each element in turn.
        for (int i = 0; i < size; i++) {
            Array.set(result, i, coerceToType(ctx, Array.get(obj, i), componentType));
        }

        return result;
    }

    public static final boolean isBigDecimalOp(final Object obj0,
            final Object obj1) {
        return (obj0 instanceof BigDecimal || obj1 instanceof BigDecimal);
    }

    public static final boolean isBigIntegerOp(final Object obj0,
            final Object obj1) {
        return (obj0 instanceof BigInteger || obj1 instanceof BigInteger);
    }

    public static final boolean isDoubleOp(final Object obj0, final Object obj1) {
        return (obj0 instanceof Double
                || obj1 instanceof Double
                || obj0 instanceof Float
                || obj1 instanceof Float);
    }

    public static final boolean isLongOp(final Object obj0, final Object obj1) {
        return (obj0 instanceof Long
                || obj1 instanceof Long
                || obj0 instanceof Integer
                || obj1 instanceof Integer
                || obj0 instanceof Character
                || obj1 instanceof Character
                || obj0 instanceof Short
                || obj1 instanceof Short
                || obj0 instanceof Byte
                || obj1 instanceof Byte);
    }

    public static final boolean isStringFloat(final String str) {
        int len = str.length();
        if (len > 1) {
            for (int i = 0; i < len; i++) {
                switch (str.charAt(i)) {
                case 'E':
                    return true;
                case 'e':
                    return true;
                case '.':
                    return true;
                }
            }
        }
        return false;
    }

    /**
     *
     */
    public ELSupport() {
        super();
    }

}
