/*
 * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
 * Copyright (c) 2010, Niclas Hehdman. All Rights Reserved.
 * Copyright (c) 2012-2014, Paul Merlin. All Rights Reserved.
 *
 * Licensed 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.qi4j.spi.value;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
import org.qi4j.api.association.AssociationDescriptor;
import org.qi4j.api.entity.EntityReference;
import org.qi4j.api.injection.scope.Service;
import org.qi4j.api.injection.scope.Structure;
import org.qi4j.api.property.PropertyDescriptor;
import org.qi4j.api.service.ServiceReference;
import org.qi4j.api.structure.Application;
import org.qi4j.api.structure.Module;
import org.qi4j.api.type.CollectionType;
import org.qi4j.api.type.EnumType;
import org.qi4j.api.type.MapType;
import org.qi4j.api.type.ValueCompositeType;
import org.qi4j.api.type.ValueType;
import org.qi4j.api.util.Base64Encoder;
import org.qi4j.api.util.Dates;
import org.qi4j.api.value.ValueBuilder;
import org.qi4j.api.value.ValueDescriptor;
import org.qi4j.api.value.ValueDeserializer;
import org.qi4j.api.value.ValueSerializationException;
import org.qi4j.api.value.ValueSerializer;
import org.qi4j.functional.Function;
import org.qi4j.functional.Function2;

import static org.qi4j.functional.Iterables.empty;
import static org.qi4j.functional.Iterables.first;

/**
 * Adapter for pull-parsing and tree-parsing capable ValueDeserializers.
 *
 * <p>
 *     Among Plain values (see {@link ValueDeserializer}) some are considered primitives to underlying serialization
 *     mechanisms and by so handed/come without conversion to/from implementations. Primitive values can be one of:
 * </p>
 * <ul>
 *     <li>String,</li>
 *     <li>Character or char,</li>
 *     <li>Boolean or boolean,</li>
 *     <li>Integer or int,</li>
 *     <li>Long or long,</li>
 *     <li>Short or short,</li>
 *     <li>Byte or byte,</li>
 *     <li>Float or float,</li>
 *     <li>Double or double.</li>
 * </ul>
 * <p>
 *     Some other Plain values are expected in given formats:
 * </p>
 * <ul>
 *     <li>BigInteger and BigDecimal depends on {@link org.qi4j.api.value.ValueSerializer.Options};</li>
 *     <li>Date as String in ISO-8601, {@literal @millis@} or {@literal /Date(..)} Microsoft format;</li>
 *     <li>DateTime (JodaTime) as a ISO-8601 String with optional timezone offset;</li>
 *     <li>LocalDateTime (JodaTime) as whatever {@link LocalDateTime#LocalDateTime(java.lang.Object)} accept as {@literal instant};</li>
 *     <li>LocalDate (JodaTime) as whatever {@link LocalDate#LocalDate(java.lang.Object)} accept as {@literal instant};</li>
 * </ul>
 *
 * @param <InputType> Implementor pull-parser type
 * @param <InputNodeType> Implementor tree-parser node type
 */
public abstract class ValueDeserializerAdapter<InputType, InputNodeType>
    implements ValueDeserializer
{
    public static interface ComplexDeserializer<T, InputType, InputNodeType>
    {
        T deserializePull( InputType input )
            throws Exception;

        T deserializeTree( InputNodeType inputNode )
            throws Exception;
    }

    private static final String UTF_8 = "UTF-8";
    private final Map<Class<?>, Function<Object, Object>> deserializers = new HashMap<>( 16 );
    private final Map<Class<?>, ComplexDeserializer<Object, InputType, InputNodeType>> complexDeserializers = new HashMap<>( 2 );
    private final Application application;
    private final Module module;
    private Function<Application, Module> valuesModuleFinder;
    private Module valuesModule;

    /**
     * Register a Plain Value type deserialization Function.
     *
     * @param <T> Plain Value parametrized Type
     * @param type Plain Value Type
     * @param deserializer Deserialization Function
     */
    @SuppressWarnings( "unchecked" )
    protected final <T> void registerDeserializer( Class<T> type, Function<Object, T> deserializer )
    {
        deserializers.put( type, (Function<Object, Object>) deserializer );
    }

    @SuppressWarnings( { "UnusedDeclaration", "unchecked" } )
    protected final <T> void registerComplexDeserializer( Class<T> type,
                                                          ComplexDeserializer<T, InputType, InputNodeType> deserializer )
    {
        complexDeserializers.put( type, (ComplexDeserializer<Object, InputType, InputNodeType>) deserializer );
    }

    @SuppressWarnings( "unchecked" )
    public ValueDeserializerAdapter( @Structure Application application,
                                     @Structure Module module,
                                     @Service ServiceReference<ValueDeserializer> serviceRef )
    {
        this( application, module, serviceRef.metaInfo( Function.class ) );
    }

    protected ValueDeserializerAdapter( Application application,
                                        Module module,
                                        Function<Application, Module> valuesModuleFinder )
    {

        this.application = application;
        this.module = module;
        setValuesModuleFinder( valuesModuleFinder );

        // Primitive Value types
        registerDeserializer( String.class, new Function<Object, String>()
        {
            @Override
            public String map( Object input )
            {
                return input.toString();
            }
        } );
        registerDeserializer( Character.class, new Function<Object, Character>()
        {
            @Override
            public Character map( Object input )
            {
                return input.toString().charAt( 0 );
            }
        } );
        registerDeserializer( Boolean.class, new Function<Object, Boolean>()
        {
            @SuppressWarnings( "UnnecessaryUnboxing" )
            @Override
            public Boolean map( Object input )
            {
                return ( input instanceof String )
                       ? Boolean.parseBoolean( (String) input )
                       : ( (Boolean) input ).booleanValue();
            }
        } );
        registerDeserializer( Integer.class, new Function<Object, Integer>()
        {
            @Override
            public Integer map( Object input )
            {
                return ( input instanceof String )
                       ? Integer.parseInt( (String) input )
                       : ( (Number) input ).intValue();
            }
        } );
        registerDeserializer( Long.class, new Function<Object, Long>()
        {
            @Override
            public Long map( Object input )
            {
                return ( input instanceof String )
                       ? Long.parseLong( (String) input )
                       : ( (Number) input ).longValue();
            }
        } );
        registerDeserializer( Short.class, new Function<Object, Short>()
        {
            @Override
            public Short map( Object input )
            {
                return ( input instanceof String )
                       ? Short.parseShort( (String) input )
                       : ( (Number) input ).shortValue();
            }
        } );
        registerDeserializer( Byte.class, new Function<Object, Byte>()
        {
            @Override
            public Byte map( Object input )
            {
                return ( input instanceof String )
                       ? Byte.parseByte( (String) input )
                       : ( (Number) input ).byteValue();
            }
        } );
        registerDeserializer( Float.class, new Function<Object, Float>()
        {
            @Override
            public Float map( Object input )
            {
                return ( input instanceof String )
                       ? Float.parseFloat( (String) input )
                       : ( (Number) input ).floatValue();
            }
        } );
        registerDeserializer( Double.class, new Function<Object, Double>()
        {
            @Override
            public Double map( Object input )
            {
                return ( input instanceof String )
                       ? Double.parseDouble( (String) input )
                       : ( (Number) input ).doubleValue();
            }
        } );

        // Number types
        registerDeserializer( BigDecimal.class, new Function<Object, BigDecimal>()
        {
            @Override
            public BigDecimal map( Object input )
            {
                return new BigDecimal( input.toString() );
            }
        } );
        registerDeserializer( BigInteger.class, new Function<Object, BigInteger>()
        {
            @Override
            public BigInteger map( Object input )
            {
                return new BigInteger( input.toString() );
            }
        } );

        // Date types
        registerDeserializer( Date.class, new Function<Object, Date>()
        {
            @Override
            public Date map( Object input )
            {
                return Dates.fromString( input.toString() );
            }
        } );
        registerDeserializer( DateTime.class, new Function<Object, DateTime>()
        {
            @Override
            public DateTime map( Object input )
            {
                return DateTime.parse( input.toString() );
            }
        } );
        registerDeserializer( LocalDateTime.class, new Function<Object, LocalDateTime>()
        {
            @Override
            public LocalDateTime map( Object input )
            {
                return new LocalDateTime( input );
            }
        } );
        registerDeserializer( LocalDate.class, new Function<Object, LocalDate>()
        {
            @Override
            public LocalDate map( Object input )
            {
                return new LocalDate( input );
            }
        } );

        // Other supported types
        registerDeserializer( EntityReference.class, new Function<Object, EntityReference>()
        {
            @Override
            public EntityReference map( Object input )
            {
                return EntityReference.parseEntityReference( input.toString() );
            }
        } );
    }

    private void setValuesModuleFinder( Function<Application, Module> valuesModuleFinder )
    {
        this.valuesModuleFinder = valuesModuleFinder;
        this.valuesModule = null;
    }

    private Module valuesModule()
    {
        if( valuesModule == null )
        {
            if( valuesModuleFinder == null )
            {
                valuesModule = module;
            }
            else
            {
                valuesModule = valuesModuleFinder.map( application );
                if( valuesModule == null )
                {
                    throw new ValueSerializationException( "Values Module provided by the finder Function was null." );
                }
            }
        }
        return valuesModule;
    }

    @Override
    public <T> Function<String, T> deserialize( Class<T> type )
    {
        if( CollectionType.isCollection( type ) )
        {
            ValueType objectValueType = new ValueType( Object.class );
            return deserialize( new CollectionType( type, objectValueType ) );
        }
        if( MapType.isMap( type ) )
        {
            ValueType objectValueType = new ValueType( Object.class );
            return deserialize( new MapType( type, objectValueType, objectValueType ) );
        }
        return deserialize( new ValueType( type ) );
    }

    @Override
    public final <T> Function<String, T> deserialize( final ValueType valueType )
    {
        return new Function<String, T>()
        {
            @Override
            public T map( String input )
            {
                return deserialize( valueType, input );
            }
        };
    }

    @Override
    public final <T> Function2<ValueType, String, T> deserialize()
    {
        return new Function2<ValueType, String, T>()
        {
            @Override
            public T map( ValueType valueType, String input )
            {
                return deserialize( valueType, input );
            }
        };
    }

    @Override
    public final <T> T deserialize( Class<?> type, String input )
        throws ValueSerializationException
    {
        if( CollectionType.isCollection( type ) )
        {
            ValueType objectValueType = new ValueType( Object.class );
            return deserialize( new CollectionType( type, objectValueType ), input );
        }
        if( MapType.isMap( type ) )
        {
            ValueType objectValueType = new ValueType( Object.class );
            return deserialize( new MapType( type, objectValueType, objectValueType ), input );
        }
        return deserialize( new ValueType( type ), input );
    }

    @Override
    public final <T> T deserialize( ValueType valueType, String input )
        throws ValueSerializationException
    {
        try
        {
            return deserializeRoot( valueType, new ByteArrayInputStream( input.getBytes( UTF_8 ) ) );
        }
        catch( ValueSerializationException ex )
        {
            throw ex;
        }
        catch( Exception ex )
        {
            throw new ValueSerializationException( "Could not deserialize value", ex );
        }
    }

    @Override
    public final <T> T deserialize( Class<?> type, InputStream input )
        throws ValueSerializationException
    {
        if( CollectionType.isCollection( type ) )
        {
            ValueType objectValueType = new ValueType( Object.class );
            return deserialize( new CollectionType( type, objectValueType ), input );
        }
        if( MapType.isMap( type ) )
        {
            ValueType objectValueType = new ValueType( Object.class );
            return deserialize( new MapType( type, objectValueType, objectValueType ), input );
        }
        return deserialize( new ValueType( type ), input );
    }

    @Override
    public final <T> T deserialize( ValueType valueType, InputStream input )
        throws ValueSerializationException
    {
        try
        {
            return deserializeRoot( valueType, input );
        }
        catch( ValueSerializationException ex )
        {
            throw ex;
        }
        catch( Exception ex )
        {
            throw new ValueSerializationException( "Could not deserialize value", ex );
        }
    }

    @SuppressWarnings( "unchecked" )
    private <T> T deserializeRoot( ValueType valueType, InputStream input )
        throws Exception
    {
        final Class<?> type = first( valueType.types() );
        // Plain ValueType
        if( deserializers.get( type ) != null )
        {
            Scanner scanner = new Scanner( input, UTF_8 ).useDelimiter( "\\A" );
            if( !scanner.hasNext() )
            {
                return String.class.equals( type ) ? (T) "" : null;
            }
            String string = scanner.next();
            return (T) deserializers.get( type ).map( string );
        }
        else // Array ValueType
        if( type.isArray() )
        {
            Scanner scanner = new Scanner( input, UTF_8 ).useDelimiter( "\\A" );
            if( !scanner.hasNext() )
            {
                return null;
            }
            String string = scanner.next();
            return (T) deserializeBase64Serialized( string );
        }
        else // Complex ValueType
        {
            InputType adaptedInput = adaptInput( input );
            onDeserializationStart( valueType, adaptedInput );
            T deserialized = doDeserialize( valueType, adaptedInput );
            onDeserializationEnd( valueType, adaptedInput );
            return deserialized;
        }
    }

    @SuppressWarnings( "unchecked" )
    private <T> T doDeserialize( ValueType valueType, InputType input )
        throws Exception
    {
        final Class<?> type = first( valueType.types() );
        // Registered deserializers
        if( deserializers.get( type ) != null )
        {
            Object value = readPlainValue( input );
            if( value == null )
            {
                return null;
            }
            return (T) deserializers.get( type ).map( value );
        }
        else if( complexDeserializers.get( type ) != null )
        {
            return (T) complexDeserializers.get( type ).deserializePull( input );
        }
        else // Explicit ValueComposite
        if( ValueCompositeType.class.isAssignableFrom( valueType.getClass() ) )
        {
            return (T) deserializeValueComposite( valueType, input );
        }
        else // Explicit Collections
        if( CollectionType.class.isAssignableFrom( valueType.getClass() ) )
        {
            return (T) deserializeCollection( (CollectionType) valueType, input );
        }
        else // Explicit Map
        if( MapType.class.isAssignableFrom( valueType.getClass() ) )
        {
            return (T) deserializeMap( (MapType) valueType, input );
        }
        else // Enum
        if( EnumType.class.isAssignableFrom( valueType.getClass() ) || type.isEnum() )
        {
            return (T) Enum.valueOf( (Class) type, readPlainValue( input ).toString() );
        }
        else // Array
        if( type.isArray() )
        {
            return (T) deserializeBase64Serialized( readPlainValue( input ).toString() );
        }
        // Guessed Deserialization
        return (T) deserializeGuessed( valueType, input );
    }

    private <T> Function<InputType, T> buildDeserializeInputFunction( final ValueType valueType )
    {
        return new Function<InputType, T>()
        {
            @Override
            public T map( InputType input )
            {
                try
                {
                    return doDeserialize( valueType, input );
                }
                catch( ValueSerializationException ex )
                {
                    throw ex;
                }
                catch( Exception ex )
                {
                    throw new ValueSerializationException( ex );
                }
            }
        };
    }

    private <T> Collection<T> deserializeCollection( CollectionType collectionType, InputType input )
        throws Exception
    {
        Collection<T> collection;
        Class<?> collectionMainType = first( collectionType.types() );
        if( Set.class.equals( collectionMainType ) )
        {
            collection = new LinkedHashSet<>();
        }
        else
        {
            collection = new ArrayList<>();
        }
        return readArrayInCollection( input,
                                      this.<T>buildDeserializeInputFunction( collectionType.collectedType() ),
                                      collection );
    }

    private <K, V> Map<K, V> deserializeMap( MapType mapType, InputType input )
        throws Exception
    {
        return readMapInMap( input,
                             this.<K>buildDeserializeInputFunction( mapType.keyType() ),
                             this.<V>buildDeserializeInputFunction( mapType.valueType() ),
                             new HashMap<K, V>() );
    }

    private <T> T deserializeValueComposite( ValueType valueType, InputType input )
        throws Exception
    {
        InputNodeType inputNode = readObjectTree( input );
        if( inputNode == null )
        {
            return null;
        }
        return deserializeNodeValueComposite( valueType, inputNode );
    }

    private <T> T deserializeNodeValueComposite( ValueType valueType, InputNodeType inputNode )
        throws Exception
    {
        ValueCompositeType valueCompositeType = (ValueCompositeType) valueType;
        Class<?> valueBuilderType = first( valueCompositeType.types() );
        String typeInfo = this.getObjectFieldValue(
            inputNode,
            "_type",
            this.<String>buildDeserializeInputNodeFunction( new ValueType( String.class ) ) );
        if( typeInfo != null )
        {
            ValueDescriptor valueDescriptor = valuesModule().valueDescriptor( typeInfo );
            if( valueDescriptor == null )
            {
                throw new ValueSerializationException( "Specified value type could not be resolved: " + typeInfo );
            }
            valueCompositeType = valueDescriptor.valueType();
            valueBuilderType = Class.forName( typeInfo );
        }
        return deserializeValueComposite( valueCompositeType, valueBuilderType, inputNode );
    }

    @SuppressWarnings( "unchecked" )
    private <T> T deserializeValueComposite( ValueCompositeType valueCompositeType, Class<?> valueBuilderType, InputNodeType inputNode )
        throws Exception
    {
        final Map<String, Object> stateMap = new HashMap<>();

        // Properties
        for( PropertyDescriptor property : valueCompositeType.properties() )
        {
            String propertyName = property.qualifiedName().name();
            Object value;
            if( objectHasField( inputNode, propertyName ) )
            {
                value = getObjectFieldValue(
                    inputNode,
                    propertyName,
                    buildDeserializeInputNodeFunction( property.valueType() ) );
                if( property.isImmutable() )
                {
                    if( value instanceof Set )
                    {
                        value = Collections.unmodifiableSet( (Set<?>) value );
                    }
                    else if( value instanceof List )
                    {
                        value = Collections.unmodifiableList( (List<?>) value );
                    }
                    else if( value instanceof Map )
                    {
                        value = Collections.unmodifiableMap( (Map<?, ?>) value );
                    }
                }
            }
            else
            {
                // Serialized object does not contain the field, try to default it
                value = property.initialValue( valuesModule() );
            }
            stateMap.put( propertyName, value );
        }

        // Associations
        for( AssociationDescriptor association : valueCompositeType.associations() )
        {
            String associationName = association.qualifiedName().name();
            if( objectHasField( inputNode, associationName ) )
            {
                Object value = getObjectFieldValue(
                    inputNode,
                    associationName,
                    buildDeserializeInputNodeFunction( new ValueType( EntityReference.class ) ) );
                stateMap.put( associationName, value );
            }
        }

        // ManyAssociations
        for( AssociationDescriptor manyAssociation : valueCompositeType.manyAssociations() )
        {
            String manyAssociationName = manyAssociation.qualifiedName().name();
            if( objectHasField( inputNode, manyAssociationName ) )
            {
                Object value = getObjectFieldValue(
                    inputNode,
                    manyAssociationName,
                    buildDeserializeInputNodeFunction( new CollectionType( Collection.class,
                                                                           new ValueType( EntityReference.class ) ) ) );
                stateMap.put( manyAssociationName, value );
            }
        }

        // NamedAssociations
        for( AssociationDescriptor namedAssociation : valueCompositeType.namedAssociations() )
        {
            String namedAssociationName = namedAssociation.qualifiedName().name();
            if( objectHasField( inputNode, namedAssociationName ) )
            {
                Object value = getObjectFieldValue(
                    inputNode,
                    namedAssociationName,
                    buildDeserializeInputNodeFunction( MapType.of( String.class, EntityReference.class, MapType.Variant.object ) ) );
                stateMap.put( namedAssociationName, value );
            }
        }

        ValueBuilder<?> valueBuilder = buildNewValueBuilderWithState( valueBuilderType, stateMap );
        return (T) valueBuilder.newInstance(); // Unchecked cast because the builder could use a type != T
    }

    private <T> Function<InputNodeType, T> buildDeserializeInputNodeFunction( final ValueType valueType )
    {
        return new Function<InputNodeType, T>()
        {
            @Override
            public T map( InputNodeType inputNode )
            {
                try
                {
                    return doDeserializeInputNodeValue( valueType, inputNode );
                }
                catch( ValueSerializationException ex )
                {
                    throw ex;
                }
                catch( Exception ex )
                {
                    throw new ValueSerializationException( ex );
                }
            }
        };
    }

    @SuppressWarnings( "unchecked" )
    private <T> T doDeserializeInputNodeValue( ValueType valueType, InputNodeType inputNode )
        throws Exception
    {
        if( inputNode == null )
        {
            return null;
        }
        final Class<?> type = first( valueType.types() );
        // Registered deserializers
        if( deserializers.get( type ) != null )
        {
            Object value = asSimpleValue( inputNode );
            if( value == null )
            {
                return null;
            }
            return (T) deserializers.get( type ).map( value );
        }
        else if( complexDeserializers.get( type ) != null )
        {
            return (T) complexDeserializers.get( type ).deserializeTree( inputNode );
        }
        else // Explicit ValueComposite
        if( ValueCompositeType.class.isAssignableFrom( valueType.getClass() ) )
        {
            return (T) deserializeNodeValueComposite( valueType, inputNode );
        }
        else // Explicit Collections
        if( CollectionType.class.isAssignableFrom( valueType.getClass() ) )
        {
            return (T) deserializeNodeCollection( (CollectionType) valueType, inputNode );
        }
        else // Explicit Map
        if( MapType.class.isAssignableFrom( valueType.getClass() ) )
        {
            MapType mapType = (MapType) valueType;
            if( mapType.variant().equals( MapType.Variant.entry ) )
            {
                return (T) deserializeNodeEntryMap( (MapType) valueType, inputNode );
            }
            else
            {
                return (T) deserializeNodeObjectMap( (MapType) valueType, inputNode );
            }
        }
        else // Enum
        if( EnumType.class.isAssignableFrom( valueType.getClass() ) || type.isEnum() )
        {
            Object value = asSimpleValue( inputNode );
            if( value == null )
            {
                return null;
            }
            return (T) Enum.valueOf( (Class) type, value.toString() );
        }
        // Guessed deserialization
        return (T) deserializeNodeGuessed( valueType, inputNode );
    }

    private ValueBuilder<?> buildNewValueBuilderWithState( Class<?> type, final Map<String, Object> stateMap )
    {
        return valuesModule().newValueBuilderWithState(
            type,
            new Function<PropertyDescriptor, Object>()
        {
            @Override
            public Object map( PropertyDescriptor property )
            {
                return stateMap.get( property.qualifiedName().name() );
            }
            },
            new Function<AssociationDescriptor, EntityReference>()
            {
                @Override
                public EntityReference map( AssociationDescriptor association )
                {
                    Object entityRef = stateMap.get( association.qualifiedName().name() );
                    if( entityRef == null )
                    {
                        return null;
                    }
                    return (EntityReference) entityRef;
                }
            },
            new Function<AssociationDescriptor, Iterable<EntityReference>>()
            {
                @Override
                @SuppressWarnings( "unchecked" )
                public Iterable<EntityReference> map( AssociationDescriptor manyAssociation )
                {
                    Object entityRefs = stateMap.get( manyAssociation.qualifiedName().name() );
                    if( entityRefs == null )
                    {
                        return empty();
                    }
                    return (Iterable<EntityReference>) entityRefs;
                }
            },
            new Function<AssociationDescriptor, Map<String, EntityReference>>()
            {
                @Override
                @SuppressWarnings( "unchecked" )
                public Map<String, EntityReference> map( AssociationDescriptor namedAssociation )
                {
                    Object entityRefs = stateMap.get( namedAssociation.qualifiedName().name() );
                    if( entityRefs == null )
                    {
                        return Collections.emptyMap();
                    }
                    return (Map<String, EntityReference>) entityRefs;
                }
            } );
    }

    @SuppressWarnings( "unchecked" )
    private <T> T deserializeGuessed( ValueType valueType, InputType input )
        throws Exception
    {
        InputNodeType inputNode = readObjectTree( input );
        if( inputNode == null )
        {
            return null;
        }
        return deserializeNodeGuessed( valueType, inputNode );
    }

    private <T> Collection<T> deserializeNodeCollection( CollectionType collectionType, InputNodeType inputNode )
        throws Exception
    {
        Collection<T> collection;
        Class<?> collectionMainType = first( collectionType.types() );
        if( Set.class.equals( collectionMainType ) )
        {
            collection = new LinkedHashSet<>();
        }
        else
        {
            collection = new ArrayList<>();
        }
        putArrayNodeInCollection( inputNode,
                                  this.<T>buildDeserializeInputNodeFunction( collectionType.collectedType() ),
                                  collection );
        return collection;
    }

    private <K, V> Map<K, V> deserializeNodeEntryMap( MapType mapType, InputNodeType inputNode )
        throws Exception
    {
        Map<K, V> map = new HashMap<>();
        putArrayNodeInMap( inputNode,
                           this.<K>buildDeserializeInputNodeFunction( mapType.keyType() ),
                           this.<V>buildDeserializeInputNodeFunction( mapType.valueType() ),
                           map );
        return map;
    }

    private <V> Map<String, V> deserializeNodeObjectMap( MapType mapType, InputNodeType inputNode )
        throws Exception
    {
        Map<String, V> map = new HashMap<>();
        putObjectNodeInMap( inputNode,
                            this.<V>buildDeserializeInputNodeFunction( mapType.valueType() ),
                            map );
        return map;
    }

    @SuppressWarnings( "unchecked" )
    private <T> T deserializeNodeGuessed( ValueType valueType, InputNodeType inputNode )
        throws Exception
    {
        if( isObjectValue( inputNode ) )
        {
            // Attempt ValueComposite deserialization
            ValueCompositeType valueCompositeType;
            if( objectHasField( inputNode, "_type" ) ) // with _type info
            {
                String typeInfo = this.getObjectFieldValue(
                    inputNode,
                    "_type",
                    this.<String>buildDeserializeInputNodeFunction( new ValueType( String.class ) ) );
                ValueDescriptor valueDescriptor = valuesModule().valueDescriptor( typeInfo );
                if( valueDescriptor == null )
                {
                    throw new ValueSerializationException( "Specified value type could not be resolved: " + typeInfo );
                }
                valueCompositeType = valueDescriptor.valueType();
            }
            else // without _type info
            {
                ValueDescriptor valueDescriptor = valuesModule().valueDescriptor( first( valueType.types() ).getName() );
                if( valueDescriptor == null )
                {
                    throw new ValueSerializationException( "Don't know how to deserialize " + inputNode );
                }
                valueCompositeType = valueDescriptor.valueType();
            }
            Class<?> valueBuilderType = first( valueCompositeType.types() );
            return deserializeValueComposite( valueCompositeType, valueBuilderType, inputNode );
        }
        // Last resort : base64 java deserialization
        return (T) deserializeBase64Serialized( inputNode );
    }

    @SuppressWarnings( "unchecked" )
    private <T> T deserializeBase64Serialized( InputNodeType inputNode )
        throws Exception
    {
        Object value = asSimpleValue( inputNode );
        if( value == null )
        {
            return null;
        }
        String base64 = value.toString();
        return deserializeBase64Serialized( base64 );
    }

    @SuppressWarnings( "unchecked" )
    private <T> T deserializeBase64Serialized( String inputString )
        throws Exception
    {
        byte[] bytes = inputString.getBytes( UTF_8 );
        bytes = Base64Encoder.decode( bytes );
        Object result;
        try( ObjectInputStream oin = new ObjectInputStream( new ByteArrayInputStream( bytes ) ) )
        {
            result = oin.readObject();
        }
        return (T) result;
    }

    //
    // Deserialization Extension Points
    //
    /**
     * Called by the adapter on deserialization start, after {@link #adaptInput(java.io.InputStream)}.
     *
     * @param valueType ValueType
     * @param input Input
     * @throws Exception that will be wrapped in a {@link ValueSerializationException}
     */
    @SuppressWarnings( "UnusedParameters" )
    protected void onDeserializationStart( ValueType valueType, InputType input )
        throws Exception
    {
        // NOOP
    }

    /**
     * Called by the adapter on deserialization end.
     *
     * @param valueType ValueType
     * @param input Input
     * @throws Exception that will be wrapped in a {@link ValueSerializationException}
     */
    protected void onDeserializationEnd( ValueType valueType, InputType input )
        throws Exception
    {
        // NOOP
    }

    //
    // Pull Parsing Deserialization
    //
    /**
     * This method is always called first, this is a chance to wrap the input type.
     *
     * @param input InputStream to adapt
     * @return Adapted input
     * @throws Exception that will be wrapped in a {@link ValueSerializationException}
     */
    protected abstract InputType adaptInput( InputStream input )
        throws Exception;

    /**
     * @param input Input
     * @return a Plain Value read from the input
     * @throws Exception that will be wrapped in a {@link ValueSerializationException}
     */
    protected abstract Object readPlainValue( InputType input )
        throws Exception;

    /**
     * @param <T> Parameterized collection type
     * @param input Input
     * @param deserializer Deserialization function
     * @param collection Collection
     * @return The filled collection or null if no array
     * @throws Exception that will be wrapped in a {@link ValueSerializationException}
     */
    protected abstract <T> Collection<T> readArrayInCollection( InputType input,
                                                                Function<InputType, T> deserializer,
                                                                Collection<T> collection )
        throws Exception;

    /**
     * A Map&lt;K,V&gt; is serialized in an array of entries objects.
     * <p>
     *     If {@link ValueSerializer.Options#MAP_ENTRIES_AS_OBJECTS} is @{code false}, then the format is key/value
     *     explicit, such as follows;
     * </p>
     * <pre>
     * [
     *     { "key": "foo",       "value": "bar"   },
     *     { "key": "cathedral", "value": "bazar" }
     * ]
     * </pre>
     * <p>
     *     An empty Map is an empty JSON array, i.e;
     * </p>
     * <pre>
     * []
     * </pre>
     * <p>
     *     <b>
     *         NOTE: This was default in Qi4j ver 2.0 and Zest ver 2.1. In Zest 3.0 and later, the
     *         {@link ValueSerializer.Options#MAP_ENTRIES_AS_OBJECTS} must be set to @{code false} explicitly in
     *         the assmebly.
     *     </b>
     * </p>
     * <p>
     *     This allow to use any type as keys and values while keeping the Map order at the cost of having
     *     non-predictible order of key/value inside an entry object.
     * </p>
     * <p>
     * If the {@link ValueSerializer.Options#MAP_ENTRIES_AS_OBJECTS} is {@code true}, then the format is
     * object-oriented, as in regular javascript objects, such as;
     * </p>
     * <pre>
     * {
     *     { "foo" : "bar"   },
     *     { "cathedral" : "bazar" }
     * }
     * </pre>
     * <p>
     *     <b>
     *         NOTE: This was NOT default in Qi4j ver 2.0 and Zest ver 2.1. In those versions, the
     *         {@link ValueSerializer.Options#MAP_ENTRIES_AS_OBJECTS} must be set to @{code true} explicitly in
     *         the assembly to enable this format.
     *     </b>
     * </p>
     * <p>
     * This has the advantage of smaller serialized format, and easier use in javascript, where the dot notation
     * can be used directly.
     * </p>
     * @param <K> Parameterized map key type
     * @param <V> Parameterized map value type
     * @param input Input
     * @param keyDeserializer Map key deserialization function
     * @param valueDeserializer Map value deserialization function
     * @param map Map
     * @return The filled map or null if no array
     * @throws Exception that will be wrapped in a {@link ValueSerializationException}
     */
    protected abstract <K, V> Map<K, V> readMapInMap( InputType input,
                                                      Function<InputType, K> keyDeserializer,
                                                      Function<InputType, V> valueDeserializer,
                                                      Map<K, V> map )
        throws Exception;

    /**
     * @param input Input
     * @return an InputNodeType or null if the value was null
     * @throws Exception that will be wrapped in a {@link ValueSerializationException}
     */
    protected abstract InputNodeType readObjectTree( InputType input )
        throws Exception;

    //
    // Tree Parsing Deserialization
    //
    protected abstract Object asSimpleValue( InputNodeType inputNode )
        throws Exception;

    protected abstract boolean isObjectValue( InputNodeType inputNode )
        throws Exception;

    protected abstract boolean objectHasField( InputNodeType inputNode, String key )
        throws Exception;

    /**
     * Return null if the field do not exists.
     * @param <T> Parameterized object field value type
     * @param inputNode Input Node
     * @param key Object key
     * @param valueDeserializer Deserialization function
     * @return The value of the field.
     * @throws Exception that will be wrapped in a {@link ValueSerializationException}
     */
    protected abstract <T> T getObjectFieldValue( InputNodeType inputNode,
                                                  String key,
                                                  Function<InputNodeType, T> valueDeserializer )
        throws Exception;

    protected abstract <T> void putArrayNodeInCollection( InputNodeType inputNode,
                                                          Function<InputNodeType, T> deserializer,
                                                          Collection<T> collection )
        throws Exception;

    protected abstract <K, V> void putArrayNodeInMap( InputNodeType inputNode,
                                                      Function<InputNodeType, K> keyDeserializer,
                                                      Function<InputNodeType, V> valueDeserializer,
                                                      Map<K, V> map
    )
        throws Exception;

    protected abstract <V> void putObjectNodeInMap( InputNodeType inputNode,
                                                    Function<InputNodeType, V> valueDeserializer,
                                                    Map<String, V> map
    )
        throws Exception;
}
