/*
 * 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 flex.messaging.io.amf.translator.decoder;

import flex.messaging.io.TypeMarshallingContext;
import flex.messaging.io.amf.ASObject;
import flex.messaging.io.amf.translator.TranslationException;

import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.Map;

/**
 * Utility class that tries to find an ActionScriptDecoder that will be able
 * to convert the encoded object into an instance of the desired class.
 *
 * @see ActionScriptDecoder
 */
public class DecoderFactory {
    // The identity transform
    private static final NativeDecoder nativeDecoder = new NativeDecoder();

    // Special null transform, always returns null
    private static final NullDecoder nullDecoder = new NullDecoder();

    // Simple types (do not have the concept of a creating a placeholder or 'shell')
    private static final NumberDecoder numberDecoder = new NumberDecoder();
    private static final StringDecoder stringDecoder = new StringDecoder();
    private static final BooleanDecoder booleanDecoder = new BooleanDecoder();
    private static final CharacterDecoder characterDecoder = new CharacterDecoder();

    // Historically dates are simple types, but they are now considered complex
    // via AMF 3 (though they can not have empty placeholders or 'shells')
    private static final DateDecoder dateDecoder = new DateDecoder();
    private static final CalendarDecoder calendarDecoder = new CalendarDecoder();

    // Complex types (can also be used to create empty placeholders to be populated at decode time)
    private static final ArrayDecoder arrayDecoder = new ArrayDecoder();
    private static EnumDecoder enumDecoder = new EnumDecoder();
    private static final MapDecoder mapDecoder = new MapDecoder();
    private static final CollectionDecoder collectionDecoder = new CollectionDecoder();
    private static final TypedObjectDecoder typedObjectDecoder = new TypedObjectDecoder();

    // If we require references to be tracked and restored, we use deep, recursive decoders
    // however these are very expensive in terms of processing time
    private static final ArrayDecoder deepArrayDecoder = new ReferenceAwareArrayDecoder();
    private static final MapDecoder deepMapDecoder = new ReferenceAwareMapDecoder();
    private static final CollectionDecoder deepCollectionDecoder = new ReferenceAwareCollectionDecoder();
    private static final TypedObjectDecoder deepTypedObjectDecoder = new ReferenceAwareTypedObjectDecoder();


    /**
     * A simple method for obtaining a placeholder or 'shell' object that will be subsequently
     * populated by potentially some other deserializer. Decoders contain special logic to implement well
     * known Collections interfaces such as java.util.Map, java.util.Set, etc
     * and also contain utilities to create native Arrays, so this functionality has been
     * made available to other classes besides decoders.
     *
     * @param desiredClass the desire class for the decoded object
     * @return The <tt>ActionScriptDecoder</tt> to use for instances of the desired class.
     */
    public static ActionScriptDecoder getDecoderForShell(Class desiredClass) {
        if (desiredClass == null)
            return nullDecoder;

        if (Collection.class.isAssignableFrom(desiredClass))
            return collectionDecoder;

        if (Map.class.isAssignableFrom(desiredClass))
            return mapDecoder;

        if (desiredClass.isArray())
            return arrayDecoder;

        if (desiredClass.isEnum())
            return enumDecoder;

        return nativeDecoder;
    }

    /**
     * This is a faster implementation than getReferenceAwareDecoder as it doesn't track
     * or care about restoring references in the event that an instance was converted to
     * a new type. Since the all MessageDeserializes now convert directly to strongly
     * typed instances it is less likely that references will need to be tracked.
     * <p>
     * A case where a reference may have needed to be tracked would be that a Class has
     * several properties of a subtype of Object[] (i.e. Array), Collection or Map but these
     * properties were not of the default type returned by the MessageDeserializer, that
     * is ArrayList or HashMap, and that each property had the potential to point to the same
     * instance. If we didn't track the reference, then the conversion to the subtype
     * (say HashMap -> TreeMap) would effectively clone these instances.
     *
     * @param encodedObject the encoded object
     * @param desiredClass  the desire class for the decoded object
     * @return The <tt>ActionScriptDecoder</tt> to use for instances of the desired class.
     */
    public static ActionScriptDecoder getDecoder(Object encodedObject, Class desiredClass) {
        if (encodedObject != null) {
            // If we already have a suitable instance, return immediately!
            if (desiredClass.isAssignableFrom(encodedObject.getClass()))
                return nativeDecoder;

            if (String.class.equals(desiredClass))
                return stringDecoder;

            // We check Number and Boolean here as well as the encodedObejct == null case
            // as they're very common property types...
            if (isNumber(desiredClass))
                return numberDecoder;

            if (isBoolean(desiredClass))
                return booleanDecoder;

            if (Collection.class.isAssignableFrom(desiredClass))
                return collectionDecoder;

            if (Map.class.isAssignableFrom(desiredClass))
                return mapDecoder;

            if (desiredClass.isArray())
                return arrayDecoder;

            // Special Case - we have a typed ASObject and we're expecting it to
            // be converted into a new class... this would be an usual situation
            // for Mistral, however, since we now create strongly typed instances
            // from a stream
            if (isTypedObject(encodedObject))
                return typedObjectDecoder;

            if (Date.class.isAssignableFrom(desiredClass))
                return dateDecoder;

            if (Calendar.class.isAssignableFrom(desiredClass))
                return calendarDecoder;
        }

        // Null may have been sent to a primitive Java type, in which case
        // we create a default value, such as new Integer(0) for int rather
        // than create a null Integer() instance...
        if (isNumber(desiredClass))
            return numberDecoder;

        if (isBoolean(desiredClass))
            return booleanDecoder;

        if (isCharacter(desiredClass))
            return characterDecoder;

        if (encodedObject == null)
            return nullDecoder;

        if (desiredClass.isEnum())
            return enumDecoder;

        DecoderFactory.invalidType(encodedObject, desiredClass);

        // Never reached...
        return nativeDecoder;
    }

    /**
     * A considerably slower entry point for decoders as it both changes the
     * assumptions we can make about type translation and also keeps track of
     * a lot of information when a complex type is converted.
     *
     * @param encodedObject the encoded object
     * @param desiredClass  the desire class for the decoded object
     * @return The <tt>ActionScriptDecoder</tt> to use for instances of the desired class.
     */
    public static ActionScriptDecoder getReferenceAwareDecoder(Object encodedObject, Class desiredClass) {
        if (encodedObject != null) {
            if (String.class.equals(desiredClass))
                return stringDecoder;

            // We check Number and Boolean here as well as the encodedObejct == null case
            // as they're very common property types...
            if (isNumber(desiredClass))
                return numberDecoder;

            if (isBoolean(desiredClass))
                return booleanDecoder;

            if (Collection.class.isAssignableFrom(desiredClass))
                return deepCollectionDecoder;

            if (Map.class.isAssignableFrom(desiredClass))
                return deepMapDecoder;

            if (desiredClass.isArray())
                return deepArrayDecoder;

            // Special Case - we have a typed ASObject and we're expecting it to
            // be converted into a new class... this would be an usual situation
            // for Mistral, however, since we now create strongly typed instances
            // from a stream.
            if (isTypedObject(encodedObject))
                return deepTypedObjectDecoder;

            if (Date.class.isAssignableFrom(desiredClass))
                return dateDecoder;

            if (Calendar.class.isAssignableFrom(desiredClass))
                return calendarDecoder;

            if (isCharacter(desiredClass))
                return characterDecoder;

            // Last resort, just try and return the object undecoded if it's the right type
            // We do this last because at this stage if it is a complex object we won't catch
            // any Typed Object translations for properties on this type...
            if (desiredClass.isAssignableFrom(encodedObject.getClass()))
                return nativeDecoder;
        }

        // Null may have been sent to a primitive Java type, in which case
        // we create a default value, such as new Integer(0) for int rather than create
        // a null Integer() instance...
        if (isNumber(desiredClass))
            return numberDecoder;

        if (isBoolean(desiredClass))
            return booleanDecoder;

        if (isCharacter(desiredClass))
            return characterDecoder;

        if (encodedObject == null)
            return nullDecoder;

        DecoderFactory.invalidType(encodedObject, desiredClass);

        // Never reached...
        return nativeDecoder;
    }

    public static boolean isNumber(Class desiredClass) {
        boolean isNum = false;

        if (desiredClass.isPrimitive()) {
            if (desiredClass.equals(Integer.TYPE)
                    || desiredClass.equals(Double.TYPE)
                    || desiredClass.equals(Long.TYPE)
                    || desiredClass.equals(Float.TYPE)
                    || desiredClass.equals(Short.TYPE)
                    || desiredClass.equals(Byte.TYPE)) {
                isNum = true;
            }
        } else if (Number.class.isAssignableFrom(desiredClass)) {
            isNum = true;
        }

        return isNum;
    }

    public static boolean isCharacter(Class desiredClass) {
        boolean isChar = false;

        if (desiredClass.isPrimitive() && desiredClass.equals(Character.TYPE)) {
            isChar = true;
        } else if (desiredClass.equals(Character.class)) {
            isChar = true;
        }

        return isChar;
    }

    public static boolean isBoolean(Class desiredClass) {
        boolean isBool = false;

        if (desiredClass.isPrimitive() && desiredClass.equals(Boolean.TYPE)) {
            isBool = true;
        } else if (desiredClass.equals(Boolean.class)) {
            isBool = true;
        }

        return isBool;
    }

    public static boolean isCharArray(Class desiredClass) {
        boolean isCharArray = false;

        if (desiredClass.isArray()) {
            Class type = desiredClass.getComponentType();
            if (type != null && type.equals(Character.TYPE)) {
                isCharArray = true;
            }
        }

        return isCharArray;
    }

    public static boolean isTypedObject(Object encodedObject) {
        boolean typed = false;

        if (encodedObject instanceof ASObject) {
            typed = TypeMarshallingContext.getType(encodedObject) != null;
        }

        return typed;
    }

    public static void invalidType(Object object, Class desiredClass) {
        String inputType = null;

        if (object != null) {
            inputType = object.getClass().getName();
        }

        StringBuffer message = new StringBuffer("Cannot convert ");
        if (inputType != null) {
            message.append("type ").append(inputType).append(" ");
        }

        if (object != null && (object instanceof String
                || object instanceof Number
                || object instanceof Boolean
                || object instanceof Date)) {
            message.append("with value '").append(object.toString()).append("' ");
        } else if (object instanceof ASObject) {
            ASObject aso = (ASObject) object;
            message.append("with remote type specified as '").append(aso.getType()).append("' ");
        }

        message.append("to an instance of ").append(desiredClass.toString());

        TranslationException ex = new TranslationException(message.toString());
        ex.setCode("Client.Message.Deserialize.InvalidType");
        throw ex;
    }
}
