/*
 * Copyright (c) 2008, Michael Hunger 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.apache.zest.bootstrap;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
import org.apache.zest.api.common.MetaInfo;
import org.apache.zest.api.property.Property;

/**
 * Declaration of a Property or Association.
 */
public final class MetaInfoDeclaration
    implements StateDeclarations, AssociationDeclarations, ManyAssociationDeclarations, NamedAssociationDeclarations
{
    Map<Class<?>, InfoHolder<?>> mixinPropertyDeclarations = new HashMap<>();

    public MetaInfoDeclaration()
    {
    }

    public <T> MixinDeclaration<T> on( Class<T> mixinType )
    {
        @SuppressWarnings( "unchecked" )
        InfoHolder<T> propertyDeclarationHolder = (InfoHolder<T>) mixinPropertyDeclarations.get( mixinType );
        if( propertyDeclarationHolder == null )
        {
            propertyDeclarationHolder = new InfoHolder<>( mixinType );
            mixinPropertyDeclarations.put( mixinType, propertyDeclarationHolder );
        }
        return propertyDeclarationHolder;
    }

    @Override
    public MetaInfo metaInfoFor( AccessibleObject accessor )
    {
        for( Map.Entry<Class<?>, InfoHolder<?>> entry : mixinPropertyDeclarations.entrySet() )
        {
            InfoHolder<?> holder = entry.getValue();
            MetaInfo metaInfo = holder.metaInfoFor( accessor );
            if( metaInfo != null )
            {
                Class<?> mixinType = entry.getKey();
                return metaInfo.withAnnotations( mixinType )
                    .withAnnotations( accessor )
                    .withAnnotations( accessor instanceof Method ? ( (Method) accessor ).getReturnType() : ( (Field) accessor )
                        .getType() );
            }
        }
        // TODO is this code reached at all??
        Class<?> declaringType = ( (Member) accessor ).getDeclaringClass();
        return new MetaInfo().withAnnotations( declaringType )
            .withAnnotations( accessor )
            .withAnnotations( accessor instanceof Method ? ( (Method) accessor ).getReturnType() : ( (Field) accessor ).getType() );
    }

    @Override
    public Object initialValueOf( AccessibleObject accessor )
    {
        for( InfoHolder<?> propertyDeclarationHolder : mixinPropertyDeclarations.values() )
        {
            final Object initialValue = propertyDeclarationHolder.initialValueOf( accessor );
            if( initialValue != null )
            {
                return initialValue;
            }
        }
        return null;
    }

    @Override
    public boolean useDefaults( AccessibleObject accessor )
    {
        for( InfoHolder<?> propertyDeclarationHolder : mixinPropertyDeclarations.values() )
        {
            final boolean useDefaults = propertyDeclarationHolder.useDefaults( accessor );
            if( useDefaults )
            {
                return useDefaults;
            }
        }
        return false;
    }

    private static class InfoHolder<T>
        implements InvocationHandler, StateDeclarations, MixinDeclaration<T>
    {
        private final static class MethodInfo
        {
            Object initialValue;
            boolean useDefaults;
            MetaInfo metaInfo;

            private MethodInfo( MetaInfo metaInfo )
            {
                this.metaInfo = metaInfo;
            }
        }

        private final Class<T> mixinType;
        private final Map<AccessibleObject, MethodInfo> methodInfos = new HashMap<>();
        // temporary holder
        private MetaInfo metaInfo = null;

        private InfoHolder( Class<T> mixinType )
        {
            this.mixinType = mixinType;
        }

        @Override
        @SuppressWarnings( "raw" )
        public Object invoke( Object o, Method method, Object[] objects )
            throws Throwable
        {
            final MethodInfo methodInfo = new MethodInfo( metaInfo );
            methodInfo.useDefaults = true;
            methodInfos.put( method, methodInfo );
            metaInfo = null; // reset
            final Class<?> returnType = method.getReturnType();
            try
            {
                return Proxy.newProxyInstance( returnType.getClassLoader(), new Class[]{ returnType },
                                               new InvocationHandler()
                                               {
                                                   @Override
                                                   public Object invoke( Object o, Method method, Object[] objects )
                                                       throws Throwable
                                                   {
                                                       if( method.getName().equals( "set" ) )
                                                       {
                                                           methodInfo.initialValue = objects[ 0 ];
                                                       }
                                                       return null;
                                                   }
                                               } );
            }
            catch( IllegalArgumentException e )
            {
                throw new IllegalArgumentException(
                    "Only methods with " + Property.class.getName() + " as return type can have declareDefaults()" );
            }
        }

        public MethodInfo matches( AccessibleObject accessor )
        {
            return methodInfos.get( accessor );
        }

        @Override
        public MetaInfo metaInfoFor( AccessibleObject accessor )
        {
            final MethodInfo methodInfo = matches( accessor );
            if( methodInfo == null )
            {
                return null;
            }
            return methodInfo.metaInfo;
        }

        @Override
        public Object initialValueOf( AccessibleObject accessor )
        {
            final MethodInfo methodInfo = matches( accessor );
            if( methodInfo == null )
            {
                return null;
            }
            return methodInfo.initialValue;
        }

        @Override
        public boolean useDefaults( AccessibleObject accessor )
        {
            final MethodInfo methodInfo = matches( accessor );
            if( methodInfo == null )
            {
                return false;
            }
            return methodInfo.useDefaults;
        }

        // DSL Interface

        @Override
        @SuppressWarnings( "raw" )
        public T declareDefaults()
        {
            return mixinType.cast(
                Proxy.newProxyInstance( mixinType.getClassLoader(), new Class[]{ mixinType }, this ) );
        }

        @Override
        public MixinDeclaration<T> setMetaInfo( Object info )
        {
            if( metaInfo == null )
            {
                metaInfo = new MetaInfo();
            }
            metaInfo.set( info );
            return this;
        }
    }
}