/*
 * 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.felix.scr.impl.inject.internal;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.felix.scr.impl.inject.ComponentConstructor;
import org.apache.felix.scr.impl.inject.OpenStatus;
import org.apache.felix.scr.impl.inject.RefPair;
import org.apache.felix.scr.impl.inject.ScrComponentContext;
import org.apache.felix.scr.impl.inject.ValueUtils;
import org.apache.felix.scr.impl.inject.ValueUtils.ValueType;
import org.apache.felix.scr.impl.inject.field.FieldUtils;
import org.apache.felix.scr.impl.logger.ComponentLogger;
import org.apache.felix.scr.impl.metadata.ComponentMetadata;
import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
import org.osgi.service.log.LogService;

/**
 * This implementation is used to construct a component instance object,
 * call the constructor and set the activation fields.
 */
public class ComponentConstructorImpl<S> implements ComponentConstructor<S>
{
    private final Field[] activationFields;
    private final ValueType[] activationFieldTypes;

    private final Constructor<S> constructor;
    private final ValueType[] constructorArgTypes;
    private final ReferenceMetadata[] constructorRefs;

    @SuppressWarnings("unchecked")
    public ComponentConstructorImpl(final ComponentMetadata componentMetadata,
            final Class<S> componentClass,
            final ComponentLogger logger)
    {
        // constructor injection
        // get reference parameter map
        final Map<Integer, List<ReferenceMetadata>> paramMap = ( componentMetadata.getNumberOfConstructorParameters() > 0 ? new HashMap<Integer, List<ReferenceMetadata>>() : null);
        for ( final ReferenceMetadata refMetadata : componentMetadata.getDependencies())
        {
            if ( refMetadata.getParameterIndex() != null )
            {
                final int index = refMetadata.getParameterIndex();
                if ( index > componentMetadata.getNumberOfConstructorParameters() )
                {
                    // if the index (starting at 0) is equal or higher than the number of constructor arguments
                    // we log an error and ignore the reference
                    logger.log(LogService.LOG_ERROR,
                            "Ignoring reference {0} for constructor injection. Parameter index is too high.", null,
                            refMetadata.getName() );
                }
                else if ( !refMetadata.isStatic() )
                {
                    // if the reference is dynamic, we log an error and ignore the reference
                    logger.log(LogService.LOG_ERROR,
                            "Ignoring reference {0} for constructor injection. Reference is dynamic.", null,
                            refMetadata.getName() );
                }
                List<ReferenceMetadata> list = paramMap.get(index);
                if ( list == null )
                {
                    list = new ArrayList<>();
                    paramMap.put(index, list);
                }
                list.add(refMetadata);
            }
        }

        // Search constructor
        Constructor<S> found = null;
        ValueType[] foundTypes = null;
        ReferenceMetadata[] foundRefs = null;

        final Constructor<?>[] constructors = componentClass.getConstructors();
        for(final Constructor<?> c : constructors)
        {
            // we try each constructor with the right number of arguments
            if ( c.getParameterTypes().length == componentMetadata.getNumberOfConstructorParameters() )
            {
                final Constructor<S> check = (Constructor<S>) c;
                logger.log(LogService.LOG_DEBUG,
                        "Checking constructor {0}", null,
                        check );
                // check argument types
                if ( componentMetadata.getNumberOfConstructorParameters() > 0 )
                {
                    boolean hasFailure = false;
                    final Class<?>[] argTypes = check.getParameterTypes();
                    foundTypes = new ValueType[argTypes.length];
                    foundRefs = new ReferenceMetadata[argTypes.length];
                    for(int i=0; i<foundTypes.length;i++)
                    {
                        final List<ReferenceMetadata> refs = paramMap.get(i);
                        if ( refs == null )
                        {
                            foundTypes[i] = ValueUtils.getValueType(argTypes[i]);
                            if ( foundTypes[i] == ValueType.ignore )
                            {
                                logger.log(LogService.LOG_DEBUG,
                                        "Constructor argument type {0} not supported by constructor injection: {1}", null,
                                        i, argTypes[i] );
                            }
                        }
                        else
                        {
                            for(final ReferenceMetadata ref : refs)
                            {
                                final ValueType t = ValueUtils.getReferenceValueType(componentClass, ref, argTypes[i], null, logger);
                                if ( t != null )
                                {
                                    foundTypes[i] = t;
                                    foundRefs[i] = ref;
                                    break;
                                }
                            }
                            if ( foundTypes[i] == null )
                            {
                                foundTypes[i] = ValueType.ignore;
                            }
                            else
                            {
                                if ( refs.size() > 1 )
                                {
                                    logger.log(LogService.LOG_ERROR,
                                            "Several references for constructor injection of parameter {0}. Only {1} will be used out of: {2}.", null,
                                            i, foundRefs[i].getName(), getNames(refs) );
                                }
                            }
                        }

                        if ( foundTypes[i] == ValueType.ignore )
                        {
                            hasFailure = true;
                            break;
                        }
                    }
                    if ( !hasFailure )
                    {
                        found = check;
                        break;
                    }
                }
                else
                {
                    found = (Constructor<S>) c;
                    break;
                }
            }
        }

        this.constructor = found;
        this.constructorArgTypes = foundTypes;
        this.constructorRefs = foundRefs;

        // activation fields
        if ( componentMetadata.getActivationFields() != null )
        {
            activationFieldTypes = new ValueType[componentMetadata.getActivationFields().size()];
            activationFields = new Field[activationFieldTypes.length];

            int index = 0;
            for(final String fieldName : componentMetadata.getActivationFields() )
            {
                final FieldUtils.FieldSearchResult result = FieldUtils.searchField(componentClass, fieldName, logger);
                if ( result == null || result.field == null )
                {
                    activationFieldTypes[index] = null;
                    activationFields[index] = null;
                }
                else
                {
                    if ( result.usable )
                    {
                        activationFieldTypes[index] = ValueUtils.getValueType(result.field.getType());
                        activationFields[index] = result.field;
                    }
                    else
                    {
                        activationFieldTypes[index] = ValueType.ignore;
                        activationFields[index] = null;
                    }
                }

                index++;
            }
        }
        else
        {
            activationFieldTypes = ValueUtils.EMPTY_VALUE_TYPES;
            activationFields = null;
        }

        if ( constructor == null )
        {
            logger.log(LogService.LOG_ERROR,
                    "Constructor with {0} arguments not found. Component will fail.", null,
                    componentMetadata.getNumberOfConstructorParameters() );
        }
        else
        {
            logger.log(LogService.LOG_DEBUG,
                    "Found constructor with {0} arguments : {1}", null,
                    componentMetadata.getNumberOfConstructorParameters(), found );
        }
    }

    /**
     * Create a new instance
     * @param componentContext The component context
     * @param parameterMap A map of reference parameters for handling references in the
     *                     constructor
     * @return The instance
     * @throws Exception If anything goes wrong, like constructor can't be found etc.
     */
    @Override
    public <T> S newInstance(final ScrComponentContext componentContext,
            final Map<ReferenceMetadata, OpenStatus<S, ?>> parameterMap)
    throws Exception
    {
        // no constructor -> throw
        if ( constructor == null )
        {
            throw new InstantiationException("Constructor not found.");
        }

        final Object[] args;
        if ( constructorArgTypes == null )
        {
            args = null;
        }
        else
        {
            args = new Object[constructorArgTypes.length];
            for(int i=0; i<args.length; i++)
            {
                final ReferenceMetadata refMetadata = this.constructorRefs[i];
                final OpenStatus<S, ?> status = refMetadata == null ? null : parameterMap.get(refMetadata);

                if ( refMetadata == null )
                {
                    args[i] = ValueUtils.getValue(constructor.getDeclaringClass().getName(),
                            constructorArgTypes[i],
                            constructor.getParameterTypes()[i],
                            componentContext,
                            null);
                }
                else
                {
                    final List<Object> refs = refMetadata.isMultiple() ? new ArrayList<>() : null;
                    Object ref = null;
                    for(final RefPair<S, ?> refPair : status.getRefs(new AtomicInteger()))
                    {
                        if ( !refPair.isDeleted() && !refPair.isFailed() )
                        {
                            if ( refPair.getServiceObject(componentContext) == null
                                    && (constructorArgTypes[i] == ValueType.ref_serviceType
                                    || constructorArgTypes[i] == ValueType.ref_tuple
                                    || constructorArgTypes[i] == ValueType.ref_logger
                                    || constructorArgTypes[i] == ValueType.ref_formatterLogger) )
                            {
                                refPair.getServiceObject(componentContext, componentContext.getBundleContext());
                            }
                            ref = ValueUtils.getValue(constructor.getDeclaringClass().getName(),
                                    constructorArgTypes[i],
                                    constructor.getParameterTypes()[i],
                                    componentContext,
                                    refPair);
                            if ( refMetadata.isMultiple() && ref != null )
                            {
                                refs.add(ref);
                            }
                        }
                    }
                    if ( !refMetadata.isMultiple())
                    {
                        if ( ref == null )
                        {
                            throw new InstantiationException("Unable to get service for reference " + refMetadata.getName());
                        }
                        args[i] = ref;
                    }
                    else
                    {
                        args[i] = refs;
                    }
                }
            }
        }
        final S component = constructor.newInstance(args);

        // activation fields
        for(int i = 0; i<activationFieldTypes.length; i++)
        {
            if ( activationFieldTypes[i] != null && activationFieldTypes[i] != ValueType.ignore )
            {
                final Object value = ValueUtils.getValue(constructor.getDeclaringClass().getName(),
                        activationFieldTypes[i],
                        activationFields[i].getType(),
                        componentContext,
                        null); // null is ok as activation fields are not references
                FieldUtils.setField(activationFields[i], component, value, componentContext.getLogger());
            }
        }

        return component;
    }

    private String getNames(final List<ReferenceMetadata> refs)
    {
        final StringBuilder sb = new StringBuilder();
        for(final ReferenceMetadata refMetadata : refs)
        {
            if ( sb.length() == 0 )
            {
                sb.append(refMetadata.getName());
            }
            else
            {
                sb.append(", ").append(refMetadata.getName());
            }
        }
        return sb.toString();
    }
}
