/*
 * Copyright 2010-2012 Niclas Hedhman.
 * Copyright 2011 Rickard Öberg.
 * Copyright 2013-2015 Paul Merlin.
 *
 * 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.library.conversion.values;

import java.lang.reflect.AccessibleObject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.qi4j.api.association.Association;
import org.qi4j.api.association.AssociationDescriptor;
import org.qi4j.api.association.AssociationStateDescriptor;
import org.qi4j.api.association.AssociationStateHolder;
import org.qi4j.api.association.ManyAssociation;
import org.qi4j.api.association.NamedAssociation;
import org.qi4j.api.entity.EntityComposite;
import org.qi4j.api.entity.EntityDescriptor;
import org.qi4j.api.entity.EntityReference;
import org.qi4j.api.entity.Identity;
import org.qi4j.api.injection.scope.Structure;
import org.qi4j.api.mixin.Mixins;
import org.qi4j.api.property.PropertyDescriptor;
import org.qi4j.api.structure.Module;
import org.qi4j.api.value.NoSuchValueException;
import org.qi4j.api.value.ValueBuilder;
import org.qi4j.api.value.ValueDescriptor;
import org.qi4j.functional.Function;
import org.qi4j.functional.Iterables;
import org.qi4j.spi.Qi4jSPI;

import static org.qi4j.library.conversion.values.Shared.STRING_COLLECTION_TYPE_SPEC;
import static org.qi4j.library.conversion.values.Shared.STRING_MAP_TYPE_SPEC;
import static org.qi4j.library.conversion.values.Shared.STRING_TYPE_SPEC;

/**
 * @deprecated Please use {@link org.qi4j.api.unitofwork.UnitOfWork#toValue(Class, Identity)} instead.
 */
@Mixins( EntityToValue.EntityToValueMixin.class )
public interface EntityToValue
{
    /**
     * Convert an entity to a value.
     *
     * @param <T> parametrized type of the value
     * @param valueType type of the value
     * @param entity the entity to convert to a value
     * @return the resulting value
     */
    <T> T convert( Class<T> valueType, Object entity );

    /**
     * Convert an entity to a value with an opportunity to customize its prototype.
     *
     * @param <T> parametrized type of the value
     * @param valueType type of the value
     * @param entity the entity to convert to a value
     * @param prototypeOpportunity a Function that will be mapped on the value prototype before instanciantion
     * @return the resulting value
     */
    <T> T convert( Class<T> valueType, Object entity, Function<T, T> prototypeOpportunity );

    /**
     * Convert an iterable of entities to an iterable of values.
     *
     * @param <T> parametrized type of the value
     * @param valueType type of the value
     * @param entities the entities to convert to values
     * @return the resulting values
     */
    <T> Iterable<T> convert( Class<T> valueType, Iterable<Object> entities );

    /**
     * Convert an iterable of entities to an iterable of values with an opportunity to customize their prototypes.
     *
     * @param <T> parametrized type of the value
     * @param valueType type of the value
     * @param entities the entities to convert to values
     * @param prototypeOpportunity a Function that will be mapped on each of the value prototypes before instanciation.
     * @return the resulting values
     */
    <T> Iterable<T> convert( Class<T> valueType, Iterable<Object> entities, Function<T, T> prototypeOpportunity );

    static class EntityToValueMixin
        implements EntityToValue
    {

        @Structure
        private Qi4jSPI spi;
        @Structure
        private Module module;

        @Override
        public <T> T convert( final Class<T> valueType, Object entity )
        {
            return createInstance( doConversion( valueType, entity ) );
        }

        @Override
        @SuppressWarnings( "unchecked" )
        public <T> T convert( final Class<T> valueType, Object entity, Function<T, T> prototypeOpportunity )
        {
            ValueBuilder<?> builder = doConversion( valueType, entity );
            prototypeOpportunity.map( (T) builder.prototype() );
            return createInstance( builder );
        }

        @Override
        public <T> Iterable<T> convert( final Class<T> valueType, Iterable<Object> entities )
        {
            return Iterables.map(
                new Function<Object, T>()
                {
                    @Override
                    public T map( Object entity )
                    {
                        return convert( valueType, entity );
                    }
                }, entities );
        }

        @Override
        public <T> Iterable<T> convert( final Class<T> valueType, Iterable<Object> entities, final Function<T, T> prototypeOpportunity )
        {
            return Iterables.map(
                new Function<Object, T>()
                {
                    @Override
                    public T map( Object entity )
                    {
                        return convert( valueType, entity, prototypeOpportunity );
                    }
                }, entities );
        }

        private <T> ValueBuilder<?> doConversion( final Class<T> valueType, Object entity )
        {
            ValueDescriptor valueDescriptor = module.valueDescriptor( valueType.getName() );
            if( valueDescriptor == null )
            {
                throw new NoSuchValueException( valueType.getName(), module.name() );
            }
            Unqualified unqualified = valueDescriptor.metaInfo( Unqualified.class );
//            Iterable<? extends PropertyDescriptor> properties = valueDescriptor.state().properties();
            final EntityComposite composite = (EntityComposite) entity;
            final EntityDescriptor entityDescriptor = spi.entityDescriptorFor( composite );
            final AssociationStateHolder associationState = spi.stateOf( composite );
            ValueBuilder<?> builder;

            if( unqualified == null || !unqualified.value() )
            {
                // Copy state using qualified names
                builder = module.newValueBuilderWithState(
                    valueType,
                    new Function<PropertyDescriptor, Object>()
                {
                    @Override
                    public Object map( PropertyDescriptor descriptor )
                    {
                        try
                        {
                            return associationState.propertyFor( descriptor.accessor() ).get();
                        }
                        catch( IllegalArgumentException e )
                        {
                            AssociationStateDescriptor entityState = entityDescriptor.state();
                            String associationName = descriptor.qualifiedName().name();
                            if( STRING_TYPE_SPEC.satisfiedBy( descriptor.valueType() ) )
                            {
                                // Find Association and convert to string
                                AssociationDescriptor associationDescriptor;
                                try
                                {
                                    associationDescriptor = entityState.getAssociationByName( associationName );
                                }
                                catch( IllegalArgumentException e1 )
                                {
                                    return null;
                                }
                                AccessibleObject associationMethod = associationDescriptor.accessor();
                                Object entity = associationState.associationFor( associationMethod ).get();
                                if( entity != null )
                                {
                                    return ( (Identity) entity ).identity().get();
                                }
                                else
                                {
                                    return null;
                                }
                            }
                            else if( STRING_COLLECTION_TYPE_SPEC.satisfiedBy( descriptor.valueType() ) )
                            {
                                AssociationDescriptor associationDescriptor;
                                try
                                {
                                    associationDescriptor = entityState.getManyAssociationByName( associationName );
                                }
                                catch( IllegalArgumentException e1 )
                                {
                                    return Collections.emptyList();
                                }

                                ManyAssociation<?> state = associationState.manyAssociationFor( associationDescriptor.accessor() );
                                List<String> entities = new ArrayList<>( state.count() );
                                for( Object entity : state )
                                {
                                    entities.add( ( (Identity) entity ).identity().get() );
                                }
                                return entities;
                            }
                            else if( STRING_MAP_TYPE_SPEC.satisfiedBy( descriptor.valueType() ) )
                            {
                                AssociationDescriptor associationDescriptor;
                                try
                                {
                                    associationDescriptor = entityState.getNamedAssociationByName( associationName );
                                }
                                catch( IllegalArgumentException e1 )
                                {
                                    return Collections.emptyMap();
                                }

                                NamedAssociation<?> state = associationState.namedAssociationFor( associationDescriptor.accessor() );
                                Map<String, String> entities = new LinkedHashMap<>( state.count() );
                                for( String name : state )
                                {
                                    entities.put( name, ( (Identity) state.get( name ) ).identity().get() );
                                }
                                return entities;
                            }

                            return null;
                        }
                    }
                    },
                    new Function<AssociationDescriptor, EntityReference>()
                    {
                        @Override
                        public EntityReference map( AssociationDescriptor associationDescriptor )
                        {
                            return EntityReference.entityReferenceFor(
                                associationState.associationFor( associationDescriptor.accessor() ).get() );
                        }
                    },
                    new Function<AssociationDescriptor, Iterable<EntityReference>>()
                    {
                        @Override
                        public Iterable<EntityReference> map( AssociationDescriptor associationDescriptor )
                        {
                            ManyAssociation<?> state = associationState.manyAssociationFor( associationDescriptor.accessor() );
                            List<EntityReference> refs = new ArrayList<>( state.count() );
                            for( Object entity : state )
                            {
                                refs.add( EntityReference.entityReferenceFor( entity ) );
                            }
                            return refs;
                        }
                    },
                    new Function<AssociationDescriptor, Map<String, EntityReference>>()
                    {
                        @Override
                        public Map<String, EntityReference> map( AssociationDescriptor associationDescriptor )
                        {
                            NamedAssociation<?> assoc = associationState.namedAssociationFor( associationDescriptor.accessor() );
                            Map<String, EntityReference> refs = new LinkedHashMap<>( assoc.count() );
                            for( String name : assoc )
                            {
                                refs.put( name, EntityReference.entityReferenceFor( assoc.get( name ) ) );
                            }
                            return refs;
                        }
                    } );
            }
            else
            {
                builder = module.newValueBuilderWithState(valueType,
                    new Function<PropertyDescriptor, Object>()
                {
                    @Override
                    public Object map( final PropertyDescriptor descriptor )
                    {
                        AssociationStateDescriptor entityState = entityDescriptor.state();
                        String propertyName = descriptor.qualifiedName().name();
                        try
                        {
                            PropertyDescriptor propertyDescriptor = entityState.findPropertyModelByName( propertyName );
                            return associationState.propertyFor( propertyDescriptor.accessor() ).get();
                        }
                        catch( IllegalArgumentException e )
                        {
                            if( STRING_TYPE_SPEC.satisfiedBy( descriptor.valueType() ) )
                            {
                                // Find Association and convert to string
                                AssociationDescriptor associationDescriptor;
                                try
                                {
                                    associationDescriptor = entityState.getAssociationByName( propertyName );
                                }
                                catch( IllegalArgumentException e1 )
                                {
                                    return null;
                                }

                                AccessibleObject associationMethod = associationDescriptor.accessor();
                                Object entity = associationState.associationFor( associationMethod ).get();
                                if( entity != null )
                                {
                                    return ( (Identity) entity ).identity().get();
                                }
                                else
                                {
                                    return null;
                                }
                            }
                            else if( STRING_COLLECTION_TYPE_SPEC.satisfiedBy( descriptor.valueType() ) )
                            {
                                AssociationDescriptor associationDescriptor;
                                try
                                {
                                    associationDescriptor = entityState.getManyAssociationByName( propertyName );
                                }
                                catch( IllegalArgumentException e1 )
                                {
                                    return null;
                                }

                                AccessibleObject associationMethod = associationDescriptor.accessor();
                                ManyAssociation<?> state = associationState.manyAssociationFor( associationMethod );
                                List<String> entities = new ArrayList<>( state.count() );
                                for( Object entity : state )
                                {
                                    entities.add( ( (Identity) entity ).identity().get() );
                                }
                                return entities;
                            }
                            else if( STRING_MAP_TYPE_SPEC.satisfiedBy( descriptor.valueType() ) )
                            {
                                AssociationDescriptor associationDescriptor;
                                try
                                {
                                    associationDescriptor = entityState.getNamedAssociationByName( propertyName );
                                }
                                catch( IllegalArgumentException e1 )
                                {
                                    return null;
                                }

                                AccessibleObject associationMethod = associationDescriptor.accessor();
                                NamedAssociation<?> state = associationState.namedAssociationFor( associationMethod );
                                Map<String, String> entities = new LinkedHashMap<>( state.count() );
                                for( String name : state )
                                {
                                    entities.put( name, ( (Identity) state.get( name ) ).identity().get() );
                                }
                                return entities;
                            }
                            return null;
                        }
                    }
                    },
                    new Function<AssociationDescriptor, EntityReference>()
                    {
                        @Override
                        public EntityReference map( AssociationDescriptor descriptor )
                        {
                            AssociationDescriptor associationDescriptor;
                            try
                            {
                                associationDescriptor = entityDescriptor.state()
                                    .getAssociationByName( descriptor.qualifiedName().name() );
                            }
                            catch( IllegalArgumentException e )
                            {
                                return null;
                            }

                            AccessibleObject associationMethod = associationDescriptor.accessor();
                            Association<Object> association = associationState.associationFor( associationMethod );
                            return EntityReference.entityReferenceFor( association.get() );
                        }
                    },
                    new Function<AssociationDescriptor, Iterable<EntityReference>>()
                    {
                        @Override
                        public Iterable<EntityReference> map( final AssociationDescriptor descriptor )
                        {
                            AssociationDescriptor associationDescriptor;
                            try
                            {
                                String associationName = descriptor.qualifiedName().name();
                                AssociationStateDescriptor entityState = entityDescriptor.state();
                                associationDescriptor = entityState.getManyAssociationByName( associationName );
                            }
                            catch( IllegalArgumentException e )
                            {
                                return Iterables.empty();
                            }

                            ManyAssociation<?> state = associationState.manyAssociationFor( associationDescriptor.accessor() );
                            List<EntityReference> refs = new ArrayList<>( state.count() );
                            for( Object entity : state )
                            {
                                refs.add( EntityReference.entityReferenceFor( entity ) );
                            }
                            return refs;
                        }
                    },
                    new Function<AssociationDescriptor, Map<String, EntityReference>>()
                    {
                        @Override
                        public Map<String, EntityReference> map( AssociationDescriptor descriptor )
                        {
                            AssociationDescriptor associationDescriptor;
                            try
                            {
                                String associationName = descriptor.qualifiedName().name();
                                AssociationStateDescriptor entityState = entityDescriptor.state();
                                associationDescriptor = entityState.getNamedAssociationByName( associationName );
                            }
                            catch( IllegalArgumentException e )
                            {
                                return Collections.emptyMap();
                            }
                            AccessibleObject associationMethod = associationDescriptor.accessor();
                            NamedAssociation<Object> assoc = associationState.namedAssociationFor( associationMethod );
                            Map<String, EntityReference> refs = new LinkedHashMap<>( assoc.count() );
                            for( String name : assoc )
                            {
                                refs.put( name, EntityReference.entityReferenceFor( assoc.get( name ) ) );
                            }
                            return refs;
                        }
                    } );
            }
            return builder;
        }

        @SuppressWarnings( "unchecked" )
        private <T> T createInstance( ValueBuilder<?> builder )
        {
            return (T) builder.newInstance();
        }
    }

}
