/*
 * 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.VisitableMarshallerContext;
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 VisitableMarshallerContext marshallerContext = new VisitableMarshallerContext();

    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 );
        }
    }
}
