/*
 * 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.directmemory.lightning.base;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.directmemory.lightning.Marshaller;
import org.apache.directmemory.lightning.MarshallerContext;
import org.apache.directmemory.lightning.TypeBindableMarshaller;
import org.apache.directmemory.lightning.bindings.AnnotatedBinder;
import org.apache.directmemory.lightning.bindings.AttributeBinder;
import org.apache.directmemory.lightning.bindings.ClassBinder;
import org.apache.directmemory.lightning.configuration.SerializerDefinition;
import org.apache.directmemory.lightning.configuration.TypeIntrospector;
import org.apache.directmemory.lightning.exceptions.SerializerDefinitionException;
import org.apache.directmemory.lightning.generator.DefinitionBuildingContext;
import org.apache.directmemory.lightning.generator.DefinitionVisitor;
import org.apache.directmemory.lightning.instantiator.ObjectInstantiatorFactory;
import org.apache.directmemory.lightning.internal.InternalMarshallerContext;
import org.apache.directmemory.lightning.internal.beans.introspection.AnnotatedTypeIntrospector;
import org.apache.directmemory.lightning.internal.util.TypeUtil;
import org.apache.directmemory.lightning.metadata.Attribute;
import org.apache.directmemory.lightning.metadata.PropertyDescriptor;

import com.carrotsearch.hppc.cursors.ObjectObjectCursor;

public abstract class AbstractSerializerDefinition
    implements SerializerDefinition
{

    private final InternalMarshallerContext marshallerContext = new InternalMarshallerContext();

    private final Set<SerializerDefinition> children = new HashSet<SerializerDefinition>();

    private final Map<PropertyDescriptor, Marshaller> propertyMarshallers =
        new HashMap<PropertyDescriptor, Marshaller>();

    private final Map<AnnotatedBinder, AnnotationBinderDefinition<?>> annotationBinders =
        new HashMap<AnnotatedBinder, AnnotationBinderDefinition<?>>();

    private DefinitionBuildingContext definitionBuildingContext;

    private ObjectInstantiatorFactory objectInstantiatorFactory = null;

    private Class<? extends Annotation> attributeAnnotation = null;

    private AbstractSerializerDefinition parent = null;

    @Override
    public final void configure( DefinitionBuildingContext definitionBuildingContext,
                                 ObjectInstantiatorFactory objectInstantiatorFactory )
    {
        // Save PropertyDescriptorFactory for later use in configure()
        this.definitionBuildingContext = definitionBuildingContext;

        // Save ObjectInstantiatorFactory for later use in configure()
        this.objectInstantiatorFactory = objectInstantiatorFactory;

        // Read the configuration
        configure();
    }

    @Override
    public final void acceptVisitor( DefinitionVisitor visitor )
    {
        // Start visiting
        visitor.visitSerializerDefinition( this );

        // Visit the attribute annotation if set
        Class<? extends Annotation> attributeAnnotation = findAttributeAnnotation( this );
        if ( attributeAnnotation != null )
        {
            visitor.visitAttributeAnnotation( attributeAnnotation );
        }

        // Visit all direct marshallers
        Iterator<ObjectObjectCursor<Type, Marshaller>> iterator = marshallerContext.getInternalMap().iterator();
        while ( iterator.hasNext() )
        {
            ObjectObjectCursor<Type, Marshaller> entry = iterator.next();
            visitor.visitClassDefine( entry.key, entry.value );
        }

        // Visit annotated properties
        Iterator<AnnotationBinderDefinition<?>> annotationIterator = annotationBinders.values().iterator();
        while ( annotationIterator.hasNext() )
        {
            AnnotationBinderDefinition<?> annotationBinderDefinition = annotationIterator.next();
            annotationBinderDefinition.acceptVisitor( visitor );
        }

        // Visit all property definitions
        for ( Entry<PropertyDescriptor, Marshaller> entry : propertyMarshallers.entrySet() )
        {
            visitor.visitPropertyDescriptor( entry.getKey(), entry.getValue() );

            Class<?> type = entry.getKey().getType();
            if ( type.isPrimitive() || type.isArray() && type.getComponentType().isPrimitive() )
            {
                continue;
            }

            visitor.visitClassDefine( type, entry.getValue() );
        }

        // Visit all children
        for ( SerializerDefinition child : children )
        {
            child.configure( definitionBuildingContext, objectInstantiatorFactory );
            child.acceptVisitor( visitor );
        }

        // Finalize visit
        visitor.visitFinalizeSerializerDefinition( this );
    }

    protected abstract void configure();

    protected <T> ClassBinder<T> serialize( final Class<T> clazz )
    {
        return buildClassBinder( clazz );
    }

    protected void install( SerializerDefinition childSerializer )
    {
        children.add( childSerializer );
        if ( childSerializer instanceof AbstractSerializerDefinition )
        {
            ( (AbstractSerializerDefinition) childSerializer ).parent = this;
        }
    }

    protected void describesAttributes( Class<? extends Annotation> attributeAnnotation )
    {
        this.attributeAnnotation = attributeAnnotation;
    }

    protected <V> AttributeBinder<V> attribute( final String attribute )
    {
        return new DefinedAttributeBinder<V>()
        {

            @Override
            protected void setDeclaringClass( Class<?> declaringClass )
            {
                super.setDeclaringClass( declaringClass );
                try
                {
                    Field reflectiveField = declaringClass.getDeclaredField( attribute );
                    reflectiveField.setAccessible( true );
                    property = reflectiveField;
                }
                catch ( Exception e )
                {
                    throw new SerializerDefinitionException( "Property " + property + " could not be found for type "
                        + declaringClass.getCanonicalName(), e );
                }
            }
        };
    }

    protected <V> AttributeBinder<V> attribute( final Field attribute )
    {
        return new DefinedAttributeBinder<V>()
        {

            {
                property = attribute;
                declaringClass = attribute.getDeclaringClass();
            }
        };
    }

    private <T> ClassBinder<T> buildClassBinder( final Class<T> clazz )
    {
        return new ClassBinder<T>()
        {

            @Override
            public AnnotatedBinder attributes()
            {
                return buildAnnotatedBinder( this, attributeAnnotation );
            }

            @Override
            public AnnotatedBinder attributes( Class<? extends Annotation> annotation )
            {
                return buildAnnotatedBinder( this, annotation );
            }

            @Override
            public Class<T> getType()
            {
                return clazz;
            }

            @Override
            @SuppressWarnings( "unchecked" )
            public void using( Class<?> clazz )
            {
                if ( Marshaller.class.isAssignableFrom( clazz ) )
                {
                    try
                    {
                        using( ( (Class<Marshaller>) clazz ).newInstance() );
                    }
                    catch ( Exception e )
                    {
                        throw new SerializerDefinitionException( "Marshaller class " + clazz.getCanonicalName()
                            + " could not be instantiated. Is there a standard (public) constructor?", e );
                    }
                }

            }

            @Override
            public void using( Marshaller marshaller )
            {
                if ( marshaller instanceof AbstractObjectMarshaller )
                {
                    marshallerContext.bindMarshaller( clazz,
                                                      new ObjenesisDelegatingMarshaller(
                                                                                         (AbstractObjectMarshaller) marshaller,
                                                                                         objectInstantiatorFactory ) );
                }
                else
                {
                    marshallerContext.bindMarshaller( clazz, marshaller );
                }
            }

            @Override
            public void using( TypeIntrospector typeIntrospector )
            {
                // TODO Auto-generated method stub

            }

            @Override
            public void attributes( AttributeBinder<?>... attributes )
            {
                for ( AttributeBinder<?> attribute : attributes )
                {
                    if ( attribute instanceof DefinedAttributeBinder )
                    {
                        DefinedAttributeBinder<?> binder = (DefinedAttributeBinder<?>) attribute;
                        binder.setDeclaringClass( getType() );
                        binder.build();
                    }
                }
            }
        };
    }

    private <T> AnnotatedBinder buildAnnotatedBinder( final ClassBinder<T> classBinder,
                                                      final Class<? extends Annotation> annotation )
    {

        return new AnnotatedBinder()
        {

            private final AnnotationBinderDefinition<T> binder = new AnnotationBinderDefinition<T>( classBinder );

            {
                annotationBinders.put( this, binder );
            }

            @Override
            public AnnotatedBinder exclude( String property )
            {
                binder.addExclude( property );
                return this;
            }

            @Override
            public AnnotatedBinder excludes( String... properties )
            {
                for ( String property : properties )
                {
                    binder.addExclude( property );
                }
                return this;
            }
        };
    }

    private Class<? extends Annotation> findAttributeAnnotation( AbstractSerializerDefinition abstractSerializerDefinition )
    {
        if ( attributeAnnotation != null )
        {
            return attributeAnnotation;
        }

        if ( parent != null )
        {
            return abstractSerializerDefinition.findAttributeAnnotation( parent );
        }

        return Attribute.class;
    }

    private class AnnotationBinderDefinition<T>
    {

        private final AnnotatedTypeIntrospector typeIntrospector;

        private final ClassBinder<T> classBinder;

        private final List<String> excludes = new ArrayList<String>();

        private AnnotationBinderDefinition( ClassBinder<T> classBinder )
        {
            this.typeIntrospector =
                new AnnotatedTypeIntrospector( findAttributeAnnotation( AbstractSerializerDefinition.this ), excludes );
            this.classBinder = classBinder;
        }

        public void addExclude( String exclude )
        {
            excludes.add( exclude );
        }

        public void acceptVisitor( DefinitionVisitor visitor )
        {
            MarshallerContext marshallers = combineMarshallers( AbstractSerializerDefinition.this );
            List<PropertyDescriptor> propertyDescriptors =
                typeIntrospector.introspect( classBinder.getType(), definitionBuildingContext.getMarshallerStrategy(),
                                             marshallers, definitionBuildingContext.getPropertyDescriptorFactory() );

            for ( PropertyDescriptor propertyDescriptor : propertyDescriptors )
            {
                Class<?> fieldType = propertyDescriptor.getType();
                Marshaller marshaller = propertyDescriptor.getMarshaller();
                visitor.visitAnnotatedAttribute( propertyDescriptor, marshaller );

                if ( fieldType.isPrimitive() || fieldType.isArray() && fieldType.getComponentType().isPrimitive() )
                {
                    continue;
                }

                visitor.visitClassDefine( !fieldType.isArray() ? fieldType : fieldType.getComponentType(), marshaller );
                if ( marshaller == null )
                {
                    visitFieldTypeAnnotatedProperties( !fieldType.isArray() ? fieldType : fieldType.getComponentType(),
                                                       visitor );
                }
            }
        }

        @SuppressWarnings( "unchecked" )
        private <F> void visitFieldTypeAnnotatedProperties( Class<?> type, DefinitionVisitor visitor )
        {
            ClassBinder<F> classBinder = (ClassBinder<F>) buildClassBinder( type );
            new AnnotationBinderDefinition<F>( classBinder ).acceptVisitor( visitor );
        }

        private MarshallerContext combineMarshallers( AbstractSerializerDefinition abstractSerializerDefinition )
        {
            return new InternalMarshallerContext( abstractSerializerDefinition.marshallerContext );
        }
    }

    private abstract class DefinedAttributeBinder<V>
        implements AttributeBinder<V>
    {

        protected Marshaller marshaller;

        protected Field property;

        protected Class<?> declaringClass;

        protected void setDeclaringClass( Class<?> declaringClass )
        {
            this.declaringClass = declaringClass;
        }

        @Override
        public AttributeBinder<V> using( Class<? extends Marshaller> marshaller )
        {
            try
            {
                using( marshaller.newInstance() );
                return this;
            }
            catch ( Exception e )
            {
                throw new SerializerDefinitionException( "Marshaller class " + marshaller.getCanonicalName()
                    + " could not be instantiated. Is there a standard (public) constructor?", e );
            }
        }

        @Override
        public AttributeBinder<V> using( Marshaller marshaller )
        {
            if ( marshaller instanceof TypeBindableMarshaller )
            {
                Type[] typeArguments = TypeUtil.getTypeArgument( property.getGenericType() );
                this.marshaller = ( (TypeBindableMarshaller) marshaller ).bindType( typeArguments );
            }

            return this;
        }

        private void build()
        {
            if ( marshaller == null )
            {
                marshaller =
                    definitionBuildingContext.getMarshallerStrategy().getMarshaller( property.getType(),
                                                                                     marshallerContext, true );
            }
            propertyMarshallers.put( definitionBuildingContext.getPropertyDescriptorFactory().byField( property,
                                                                                                       marshaller,
                                                                                                       declaringClass ),
                                     marshaller );
        }
    }
}
