/*
 * 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.sling.testing.mock.osgi;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.apache.felix.scr.impl.inject.Annotations;
import org.apache.sling.testing.mock.osgi.OsgiMetadataUtil.DynamicReference;
import org.apache.sling.testing.mock.osgi.OsgiMetadataUtil.FieldCollectionType;
import org.apache.sling.testing.mock.osgi.OsgiMetadataUtil.OsgiMetadata;
import org.apache.sling.testing.mock.osgi.OsgiMetadataUtil.Reference;
import org.apache.sling.testing.mock.osgi.OsgiMetadataUtil.ReferencePolicy;
import org.apache.sling.testing.mock.osgi.OsgiMetadataUtil.ReferencePolicyOption;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceObjects;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.ComponentServiceObjects;

/**
 * Helper methods to inject dependencies and activate services.
 */
final class OsgiServiceUtil {

    private OsgiServiceUtil() {
        // static methods only
    }

    /**
     * Simulate activation or deactivation of OSGi service instance.
     * @param target Service instance.
     * @param componentContext Component context
     * @return true if activation/deactivation method was called. False if it failed.
     */
    public static boolean activateDeactivate(Object target, MockComponentContext componentContext, boolean activate) {
        Class<?> targetClass = target.getClass();

        // get method name for activation/deactivation from osgi metadata
        OsgiMetadata metadata = OsgiMetadataUtil.getMetadata(targetClass);
        if (metadata == null) {
            throw new NoScrMetadataException(targetClass);
        }
        String methodName;
        if (activate) {
            methodName = metadata.getActivateMethodName();
        } else {
            methodName = metadata.getDeactivateMethodName();
        }
        boolean fallbackDefaultName = false;
        if (StringUtils.isEmpty(methodName)) {
            fallbackDefaultName = true;
            if (activate) {
                methodName = "activate";
            } else {
                methodName = "deactivate";
            }
        }

        // try to find matching activate/deactivate method and execute it
        if (invokeLifecycleMethod(target, targetClass, methodName, !activate,
                componentContext, componentContext.getPropertiesAsMap())) {
            return true;
        }

        if (fallbackDefaultName) {
            return false;
        }

        throw new RuntimeException("No matching " + (activate ? "activation" : "deactivation") + " method with name '" + methodName + "' "
                + " found in class " + targetClass.getName());
    }

    /**
     * Simulate modification of configuration of OSGi service instance.
     * @param target Service instance.
     * @param properties Updated configuration
     * @return true if modified method was called. False if it failed.
     */
    public static boolean modified(Object target, MockComponentContext componentContext, Map<String,Object> properties) {
        Class<?> targetClass = target.getClass();

        // get method name for activation/deactivation from osgi metadata
        OsgiMetadata metadata = OsgiMetadataUtil.getMetadata(targetClass);
        if (metadata == null) {
            throw new NoScrMetadataException(targetClass);
        }
        String methodName = metadata.getModifiedMethodName();
        if (StringUtils.isEmpty(methodName)) {
            return false;
        }

        // try to find matching modified method and execute it
        if (invokeLifecycleMethod(target, targetClass, methodName, false, componentContext, properties)) {
            return true;
        }

        throw new RuntimeException("No matching modified method with name '" + methodName + "' "
                + " found in class " + targetClass.getName());
    }

    /**
     * Invokes a lifecycle method (activation, deactivation or modified) with variable method arguments.
     * @param target Target object
     * @param targetClass Target object class
     * @param methodName Method name
     * @param allowIntegerArgument Allow int or Integer as arguments (only decactivate)
     * @param componentContext Component context
     * @param properties Component properties
     * @return true if a method was found and invoked
     */
    private static boolean invokeLifecycleMethod(Object target, Class<?> targetClass,
            String methodName, boolean allowIntegerArgument,
            MockComponentContext componentContext, Map<String,Object> properties) {

        // 1. componentContext
        Method method = getMethod(targetClass, methodName, new Class<?>[] { ComponentContext.class });
        if (method != null) {
            invokeMethod(target, method, new Object[] { componentContext });
            return true;
        }

        // 2. bundleContext
        method = getMethod(targetClass, methodName, new Class<?>[] { BundleContext.class });
        if (method != null) {
            invokeMethod(target, method, new Object[] { componentContext.getBundleContext() });
            return true;
        }

        // 3. map
        method = getMethod(targetClass, methodName, new Class<?>[] { Map.class });
        if (method != null) {
            invokeMethod(target, method, new Object[] { componentContext.getPropertiesAsMap() });
            return true;
        }

        // 4. Component property type (annotation lass)
        method = getMethod(targetClass, methodName, new Class<?>[] { Annotation.class });
        if (method != null) {
            invokeMethod(target, method, new Object[] { Annotations.toObject(method.getParameterTypes()[0],
                    componentContext.getPropertiesAsMap(),
                    componentContext.getBundleContext().getBundle(), false) });
            return true;
        }

        // 5. int (deactivation only)
        if (allowIntegerArgument) {
            method = getMethod(targetClass, methodName, new Class<?>[] { int.class });
            if (method != null) {
                invokeMethod(target, method, new Object[] { 0 });
                return true;
            }
        }

        // 6. Integer (deactivation only)
        if (allowIntegerArgument) {
            method = getMethod(targetClass, methodName, new Class<?>[] { Integer.class });
            if (method != null) {
                invokeMethod(target, method, new Object[] { 0 });
                return true;
            }
        }

        // 7. mixed arguments
        Class<?>[] mixedArgsAllowed = allowIntegerArgument ?
                new Class<?>[] { ComponentContext.class, BundleContext.class, Map.class, Annotation.class, int.class, Integer.class }
                : new Class<?>[] { ComponentContext.class, BundleContext.class, Map.class, Annotation.class };
        method = getMethodWithAnyCombinationArgs(targetClass, methodName, mixedArgsAllowed);
        if (method != null) {
            Object[] args = new Object[method.getParameterTypes().length];
            for (int i=0; i<args.length; i++) {
                if (method.getParameterTypes()[i] == ComponentContext.class) {
                    args[i] = componentContext;
                }
                else if (method.getParameterTypes()[i] == BundleContext.class) {
                    args[i] = componentContext.getBundleContext();
                }
                else if (method.getParameterTypes()[i] == Map.class) {
                    args[i] = componentContext.getPropertiesAsMap();
                }
                else if (method.getParameterTypes()[i].isAnnotation()) {
                    args[i] = Annotations.toObject(method.getParameterTypes()[i],
                            componentContext.getPropertiesAsMap(),
                            componentContext.getBundleContext().getBundle(), false);
                }
                else if (method.getParameterTypes()[i] == int.class || method.getParameterTypes()[i] == Integer.class) {
                    args[i] = 0;
                }
            }
            invokeMethod(target, method, args);
            return true;
        }

        // 8. noargs
        method = getMethod(targetClass, methodName, new Class<?>[0]);
        if (method != null) {
            invokeMethod(target, method, new Object[0]);
            return true;
        }

        return false;
    }

    private static Method getMethod(Class clazz, String methodName, Class<?>[] types) {
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            if (StringUtils.equals(method.getName(), methodName) && method.getParameterTypes().length==types.length) {
                boolean foundMismatch = false;
                for (int i=0; i<types.length; i++) {
                    if (!((method.getParameterTypes()[i]==types[i])
                            || (types[i]==Annotation.class && method.getParameterTypes()[i].isAnnotation()))) {
                        foundMismatch = true;
                        break;
                    }
                }
                if (!foundMismatch) {
                    return method;
                }
            }
        }
        // not found? check super classes
        Class<?> superClass = clazz.getSuperclass();
        if (superClass != null && superClass != Object.class) {
            return getMethod(superClass, methodName, types);
        }
        return null;
    }

    private static Method getMethodWithAssignableTypes(Class clazz, String methodName, Class<?>[] types) {
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            if (StringUtils.equals(method.getName(), methodName) && method.getParameterTypes().length==types.length) {
                boolean foundMismatch = false;
                for (int i=0; i<types.length; i++) {
                    if (!method.getParameterTypes()[i].isAssignableFrom(types[i])) {
                        foundMismatch = true;
                        break;
                    }
                }
                if (!foundMismatch) {
                    return method;
                }
            }
        }
        // not found? check super classes
        Class<?> superClass = clazz.getSuperclass();
        if (superClass != null && superClass != Object.class) {
            return getMethodWithAssignableTypes(superClass, methodName, types);
        }
        return null;
    }

    private static Method getMethodWithAnyCombinationArgs(Class clazz, String methodName, Class<?>[] types) {
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            if (StringUtils.equals(method.getName(), methodName) && method.getParameterTypes().length > 1) {
                boolean foundMismatch = false;
                for (Class<?> parameterType : method.getParameterTypes()) {
                    boolean foundAnyMatch = false;
                    for (int i=0; i<types.length; i++) {
                        if (types[i] == Annotation.class) {
                            if (parameterType.isAnnotation()) {
                                foundAnyMatch = true;
                                break;
                            }
                        }
                        else if (types[i] == ComponentContext.class || types[i] == BundleContext.class
                                || types[i] == ServiceReference.class || types[i] == ComponentServiceObjects.class
                                || types[i] == Map.class || types[i] == int.class || types[i] == Integer.class) {
                            if (parameterType == types[i]) {
                                foundAnyMatch = true;
                                break;
                            }
                        }
                        else if (parameterType.isAssignableFrom(types[i])) {
                            foundAnyMatch = true;
                            break;
                        }
                    }
                    if (!foundAnyMatch) {
                        foundMismatch = true;
                        break;
                    }
                }
                if (!foundMismatch) {
                    return method;
                }
            }
        }
        // not found? check super classes
        Class<?> superClass = clazz.getSuperclass();
        if (superClass != null && superClass != Object.class) {
            return getMethodWithAnyCombinationArgs(superClass, methodName, types);
        }
        return null;
    }

    private static void invokeMethod(Object target, Method method, Object[] args) {
        try {
            method.setAccessible(true);
            method.invoke(target, args);
        } catch (IllegalAccessException ex) {
            throw new RuntimeException("Unable to invoke method '" + method.getName() + "' for class "
                    + target.getClass().getName(), ex);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException("Unable to invoke method '" + method.getName() + "' for class "
                    + target.getClass().getName(), ex);
        } catch (InvocationTargetException ex) {
            throw new RuntimeException("Unable to invoke method '" + method.getName() + "' for class "
                    + target.getClass().getName(), ex.getCause());
        }
    }

    private static Field getField(Class clazz, String fieldName, Class<?> type) {
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            if (StringUtils.equals(field.getName(), fieldName) && field.getType().equals(type)) {
                return field;
            }
        }
        // not found? check super classes
        Class<?> superClass = clazz.getSuperclass();
        if (superClass != null && superClass != Object.class) {
            return getField(superClass, fieldName, type);
        }
        return null;
    }

    private static Field getFieldWithAssignableType(Class clazz, String fieldName, Class<?> type) {
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            if (StringUtils.equals(field.getName(), fieldName) && field.getType().isAssignableFrom(type)) {
                return field;
            }
        }
        // not found? check super classes
        Class<?> superClass = clazz.getSuperclass();
        if (superClass != null && superClass != Object.class) {
            return getFieldWithAssignableType(superClass, fieldName, type);
        }
        return null;
    }

    private static Field getCollectionField(Class clazz, String fieldName) {
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            if (StringUtils.equals(field.getName(), fieldName) && Collection.class.isAssignableFrom(field.getType())) {
                return field;
            }
        }
        // not found? check super classes
        Class<?> superClass = clazz.getSuperclass();
        if (superClass != null && superClass != Object.class) {
            return getCollectionField(superClass, fieldName);
        }
        return null;
    }

    private static void setField(Object target, Field field, Object value) {
        try {
            field.setAccessible(true);
            field.set(target, value);
        } catch (IllegalAccessException ex) {
            throw new RuntimeException("Unable to set field '" + field.getName() + "' for class "
                    + target.getClass().getName(), ex);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException("Unable to set field '" + field.getName() + "' for class "
                    + target.getClass().getName(), ex);
        }
    }

    /**
     * Simulate OSGi service dependency injection. Injects direct references and multiple references.
     * @param target Service instance
     * @param bundleContext Bundle context from which services are fetched to inject.
     * @param properties Services properties (used to resolve dynamic reference properties)
     * @return true if all dependencies could be injected, false if the service has no dependencies.
     */
    public static boolean injectServices(Object target, BundleContext bundleContext, Map<String, Object> properties) {

        // collect all declared reference annotations on class and field level
        Class<?> targetClass = target.getClass();

        OsgiMetadata metadata = OsgiMetadataUtil.getMetadata(targetClass);
        if (metadata == null) {
            throw new NoScrMetadataException(targetClass);
        }

        // try to inject services
        boolean foundAny = false;
        for (Reference reference : metadata.getReferences()) {
            if (reference.isConstructorParameter()) {
                continue;
            }
            if (properties != null) {
                // Look for a target override
                Object o = properties.get(reference.getName() + ".target");
                if (o instanceof String) {
                    reference = new DynamicReference(reference,(String)o);
                }
            }
            injectServiceReference(reference, target, bundleContext);
            foundAny = true;
        }
        return foundAny;
    }

    /**
     * Simulate OSGi service dependency injection. Injects direct references and multiple references.
     * @param targetClass Service class
     * @param componentContext Component context
     * @return true if all dependencies could be injected, false if the service has no dependencies.
     */
    @SuppressWarnings("null")
    public static @NotNull <T> T activateInjectServices(Class<T> targetClass, MockComponentContext componentContext) {
        T target;
        try {
            // try to find constructor with parameter matching the OSGi metadata
            target = instantiateServiceWithActivateInject(targetClass, componentContext);
            // fallback to default constructor
            if (target == null) {
                target = targetClass.newInstance();
            }
        }
        catch (IllegalAccessException | InstantiationException | InvocationTargetException ex) {
            throw new RuntimeException("Error creating instance of " + targetClass.getName() + ": " + ex.getMessage(), ex);
        }

        // check if there are additional references outside constructor, inject them as well
        injectServices(target, componentContext.getBundleContext(), componentContext.getPropertiesAsMap());

        // check for dedicated activate method
        activateDeactivate(target, componentContext, true);

        return target;
    }

    @SuppressWarnings("unchecked")
    private static @Nullable <T> T instantiateServiceWithActivateInject(Class<T> targetClass, MockComponentContext componentContext)
            throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        OsgiMetadata metadata = OsgiMetadataUtil.getMetadata(targetClass);
        if (metadata == null) {
            return null;
        }

        // get list of constructor injection references, ordered by parameter number
        List<Reference> constructorInjectionReferences = metadata.getReferences().stream()
                .filter(Reference::isConstructorParameter)
                .sorted((ref1, ref2) -> ref1.getParameter().compareTo(ref2.getParameter()))
                .collect(Collectors.toList());

        // go through all constructors and try to find a matching one
        Constructor<T> matchingConstructor = null;
        List<Object> constructorParamValues = null;
        for (Constructor<T> constructor : (Constructor<T>[])targetClass.getConstructors()) {
            Optional<List<Object>> values = buildConstructorInjectionValues(targetClass, constructor,
                    componentContext, constructorInjectionReferences);
            if (values.isPresent()) {
                matchingConstructor = constructor;
                constructorParamValues = values.get();
                break;
            }
        }
        if (matchingConstructor != null && constructorParamValues != null) {
            return matchingConstructor.newInstance(constructorParamValues.toArray(new Object[0]));
        }
        else {
            return null;
        }
    }

    private static <T> Optional<List<Object>> buildConstructorInjectionValues(Class<T> targetClass, Constructor<T> constructor,
            MockComponentContext componentContext, List<Reference> constructorInjectionReferences)
            throws InstantiationException, IllegalAccessException {
        Iterator<Reference> referenceIterator = constructorInjectionReferences.iterator();
        List<Object> values = new ArrayList<>();
        int parameterIndex = 0;
        for (Parameter parameter : constructor.getParameters()) {
            // check for well-known parameter types first
            if (parameter.getType() == ComponentContext.class) {
                values.add(componentContext);
            }
            else if (parameter.getType() == BundleContext.class) {
                values.add(componentContext.getBundleContext());
            }
            else if (parameter.getType() == Map.class) {
                values.add(componentContext.getPropertiesAsMap());
            }
            else if (parameter.getType().isAnnotation()) {
                values.add(Annotations.toObject(parameter.getType(),
                        componentContext.getPropertiesAsMap(),
                        componentContext.getBundleContext().getBundle(), false));
            }
            // check for reference injection
            else if (referenceIterator.hasNext()) {
                Reference reference = referenceIterator.next();
                Optional<?> referenceValue = buildConstructorInjectionValue(targetClass, parameter.getType(), reference, componentContext, parameterIndex++);
                if (referenceValue != null) {
                    values.add(referenceValue.isPresent() ? referenceValue.get() : null);
                }
                else {
                    // reference not found, constructor is invalid
                    return Optional.empty();
                }
            }
            else {
                // parameter does not match, constructor is invalid
                return Optional.empty();
            }
        }
        return Optional.of(values);
    }

    /**
     * Build value to be injected in constructor parameter.
     * @param <T> Parameter type
     * @param targetClass Target class containing the constructor
     * @param parameterType Parameter type
     * @param reference Reference
     * @param componentContext Component context
     * @param parameterIndex 0-based index of the constructor parameter for which the injection value is calculated
     * @return null if parameter could not be injected, empty Optional if null value should be injected, or value wrapped in Optional otherwise
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    private static <T> @Nullable Optional<?> buildConstructorInjectionValue(Class<?> targetClass, Class<T> parameterType, Reference reference,
            MockComponentContext componentContext, int parameterIndex) throws InstantiationException, IllegalAccessException {
        Class<?> type = reference.getInterfaceTypeAsClass();
        // get matching service references
        List<ServiceInfo<?>> matchingServices = getMatchingServices(type,
                componentContext.getBundleContext(), reference.getTarget());

        if (matchingServices.isEmpty() && !reference.isCardinalityOptional()) {
            throw new ReferenceViolationException("Unable to inject mandatory reference '" + reference.getName() + "' (" + type.getName() +  ") into constructor parameter " + parameterIndex + " for class " + targetClass.getName() + " : no matching services were found.");
        }

        // check for field with list/collection reference
        if (reference.isCardinalityMultiple()) {
            Collection<Object> collection = newCollectionInstance(parameterType);
            switch (reference.getFieldCollectionType()) {
                case SERVICE:
                    matchingServices.stream()
                        .map(ServiceInfo::getServiceInstance)
                        .forEach(collection::add);
                    break;
                case REFERENCE:
                    matchingServices.stream()
                        .map(ServiceInfo::getServiceReference)
                        .forEach(collection::add);
                    break;
                default:
                    throw new RuntimeException("Field collection type '" + reference.getFieldCollectionType() + "' not supported "
                            + "for reference '" + reference.getName()  + "' (" + type.getName() +  ") into constructor parameter " + parameterIndex + " for class " +  targetClass.getName());
            }
            return Optional.of(collection);
        }

        // check for single field reference
        else {
            Optional<ServiceInfo<?>> firstServiceInfo = matchingServices.stream().findFirst();

            // 1. assignable from service instance
            if (parameterType.isAssignableFrom(reference.getInterfaceTypeAsClass())) {
                return firstServiceInfo.map(ServiceInfo::getServiceInstance);
            }

            // 2. ServiceReference
            if (parameterType == ServiceReference.class) {
                return firstServiceInfo.map(ServiceInfo::getServiceReference);
            }
        }

        // no match
        return null;
    }

    private static void injectServiceReference(Reference reference, Object target, BundleContext bundleContext) {
        Class<?> targetClass = target.getClass();

        // get reference type
        Class<?> type = reference.getInterfaceTypeAsClass();

        // get matching service references
        List<ServiceInfo<?>> matchingServices = getMatchingServices(type, bundleContext, reference.getTarget());

        // no references found? check if reference was optional
        if (matchingServices.isEmpty()) {
            if (!reference.isCardinalityOptional()) {
                throw new ReferenceViolationException("Unable to inject mandatory reference '" + reference.getName() + "' (" + type.getName() +  ") for class " + targetClass.getName() + " : no matching services were found. bundleContext=" + bundleContext);
            }
            if (reference.isCardinalityMultiple()) {
                // make sure at least empty array is set
                invokeBindUnbindMethod(reference, target, null, bundleContext, true);
            }
        }

        // multiple references found? inject only first one with highest ranking
        if (matchingServices.size() > 1 && !reference.isCardinalityMultiple()) {
            matchingServices = matchingServices.subList(0, 1);
        } else {
            /*
             * Please note that the OSGi spec does not seem to define a ordering for the list of service references/services
             * https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.component.html#service.component-field.injection
             * But the actual Felix framework implementation seems to return the list always sorted by rank in ascending order, so we do the same here.
             */
            matchingServices.sort(Comparator.comparing(ServiceInfo::getServiceReference));
        }


        // try to invoke bind method
        for (ServiceInfo<?> matchingService : matchingServices) {
            invokeBindUnbindMethod(reference, target, matchingService, bundleContext, true);
        }
    }

    private static void invokeBindUnbindMethod(Reference reference, Object target, ServiceInfo<?> serviceInfo, BundleContext bundleContext, boolean bind) {
        Class<?> targetClass = target.getClass();

        // try to invoke bind method
        String methodName = bind ? reference.getBind() : reference.getUnbind();
        String fieldName = reference.getField();

        if (StringUtils.isEmpty(methodName) && StringUtils.isEmpty(fieldName)) {
            throw new RuntimeException("No bind/unbind method name or file name defined "
                    + "for reference '" + reference.getName() + "' (" + reference.getInterfaceTypeAsClass().getName() +  ") for class " +  targetClass.getName());
        }

        if (StringUtils.isNotEmpty(methodName) && serviceInfo != null) {

            // 1. ServiceReference
            Method method = getMethod(targetClass, methodName, new Class<?>[] { ServiceReference.class });
            if (method != null) {
                invokeMethod(target, method, new Object[] { serviceInfo.getServiceReference() });
                return;
            }

            // 2. ComponentServiceObjects
            method = getMethod(targetClass, methodName, new Class<?>[] { ComponentServiceObjects.class });
            if (method != null) {
                invokeMethod(target, method, new Object[] { toComponentServiceObjects(bundleContext.getServiceObjects(serviceInfo.getServiceReference())) });
                return;
            }

            // 3. assignable from service instance
            Class<?> interfaceType = reference.getInterfaceTypeAsClass();
            method = getMethodWithAssignableTypes(targetClass, methodName, new Class<?>[] { interfaceType });
            if (method != null) {
                invokeMethod(target, method, new Object[] { serviceInfo.getServiceInstance() });
                return;
            }

            // 4. Map
            method = getMethod(targetClass, methodName, new Class<?>[] { Map.class });
            if (method != null) {
                invokeMethod(target, method, new Object[] { serviceInfo.getServiceConfig() });
                return;
            }

            // 5. mixed arguments
            Class<?>[] mixedArgsAllowed = new Class<?>[] { ServiceReference.class, ComponentServiceObjects.class, interfaceType, Map.class };
            method = getMethodWithAnyCombinationArgs(targetClass, methodName, mixedArgsAllowed);
            if (method != null) {
                Object[] args = new Object[method.getParameterTypes().length];
                for (int i=0; i<args.length; i++) {
                    if (method.getParameterTypes()[i] == ServiceReference.class) {
                        args[i] = serviceInfo.getServiceReference();
                    }
                    else if (method.getParameterTypes()[i] == ComponentServiceObjects.class) {
                        args[i] = toComponentServiceObjects(bundleContext.getServiceObjects(serviceInfo.getServiceReference()));
                    }
                    else if (method.getParameterTypes()[i].isAssignableFrom(interfaceType)) {
                        args[i] = serviceInfo.getServiceInstance();
                    }
                    else if (method.getParameterTypes()[i] == Map.class) {
                        args[i] = serviceInfo.getServiceConfig();
                    }
                }
                invokeMethod(target, method, args);
                return;
            }

            throw new RuntimeException((bind ? "Bind" : "Unbind") + " method with name " + methodName + " not found "
                    + "for reference '" + reference.getName() + "' for class " +  targetClass.getName());
        }

        // OSGi declarative services 1.3 supports modifying the field directly
        else if (StringUtils.isNotEmpty(fieldName)) {

            // check for field with list/collection reference
            if (reference.isCardinalityMultiple()) {
                switch (reference.getFieldCollectionType()) {
                    case SERVICE:
                    case REFERENCE:
                        Object item = null;
                        if (serviceInfo != null) {
                            item = serviceInfo.getServiceInstance();
                            if (reference.getFieldCollectionType() == FieldCollectionType.REFERENCE) {
                                item = serviceInfo.getServiceReference();
                            }
                        }
                        Field field = getCollectionField(targetClass, fieldName);
                        if (field != null) {
                            if (bind) {
                                addToCollection(target, field, item);
                            }
                            else {
                                removeFromCollection(target, field, item);
                            }
                            return;
                        }
                        break;
                    default:
                        throw new RuntimeException("Field collection type '" + reference.getFieldCollectionType() + "' not supported "
                                + "for reference '" + reference.getName() + "' (" + reference.getInterfaceTypeAsClass().getName() +  ") for class " +  targetClass.getName());
                }
            }

            // check for single field reference
            else {
                // 1. assignable from service instance
                Class<?> interfaceType = reference.getInterfaceTypeAsClass();
                Field field = getFieldWithAssignableType(targetClass, fieldName, interfaceType);
                if (field != null) {
                    setField(target, field, bind && serviceInfo != null ? serviceInfo.getServiceInstance() : null);
                    return;
                }

                // 2. ServiceReference
                field = getField(targetClass, fieldName, ServiceReference.class);
                if (field != null) {
                    setField(target, field, bind && serviceInfo != null ? serviceInfo.getServiceReference() : null);
                    return;
                }
            }
        }

    }

    private static <T> ComponentServiceObjects<T> toComponentServiceObjects(ServiceObjects<T> serviceObjects) {
        return new ComponentServiceObjects<T>() {
            @Override
            public T getService() {
                return serviceObjects.getService();
            }
            @Override
            public void ungetService(T service) {
                serviceObjects.ungetService(service);
            }
            @Override
            public ServiceReference<T> getServiceReference() {
                return serviceObjects.getServiceReference();
            }
        };
    }

    @SuppressWarnings("unchecked")
    private static void addToCollection(Object target, Field field, Object item) {
        try {
            field.setAccessible(true);
            Collection<Object> collection = (Collection<Object>)field.get(target);
            if (collection == null) {
                collection = newCollectionInstance(field.getType());
            }
            if (item != null) {
                collection.add(item);
            }
            field.set(target, collection);

        } catch (IllegalAccessException | IllegalArgumentException | InstantiationException ex) {
            throw new RuntimeException("Unable to set field '" + field.getName() + "' for class "
                    + target.getClass().getName(), ex);
        }
    }

    @SuppressWarnings("unchecked")
    private static void removeFromCollection(Object target, Field field, Object item) {
        try {
            field.setAccessible(true);
            Collection<Object> collection = (Collection<Object>)field.get(target);
            if (collection == null) {
                collection = newCollectionInstance(field.getType());
            }
            if (item != null) {
                collection.remove(item);
            }
            field.set(target, collection);

        } catch (IllegalAccessException | IllegalArgumentException | InstantiationException ex) {
            throw new RuntimeException("Unable to set field '" + field.getName() + "' for class "
                    + target.getClass().getName(), ex);
        }
    }

    @SuppressWarnings({ "unchecked", "null" })
    private static @NotNull Collection<Object> newCollectionInstance(Class<?> collectionType)
            throws InstantiationException, IllegalAccessException {
        if (collectionType == List.class || collectionType == Collection.class) {
            return new ArrayList<>();
        }
        if (collectionType == Set.class) {
            return new HashSet<>();
        }
        if (collectionType == SortedSet.class) {
            return new TreeSet<>();
        }
        return (Collection)collectionType.newInstance();
    }

    /**
     * Directly invoke bind method on service for the given reference.
     * @param reference Reference metadata
     * @param target Target object for reference
     * @param serviceInfo Service on which to invoke the method
     * @param bundleContext Bundle context
     */
    public static void invokeBindMethod(Reference reference, Object target, ServiceInfo serviceInfo, BundleContext bundleContext) {
        invokeBindUnbindMethod(reference,  target, serviceInfo, bundleContext, true);
    }

    /**
     * Directly invoke unbind method on service for the given reference.
     * @param reference Reference metadata
     * @param target Target object for reference
     * @param serviceInfo Service on which to invoke the method
     * @param bundleContext Bundle context
     */
    public static void invokeUnbindMethod(Reference reference, Object target, ServiceInfo serviceInfo, BundleContext bundleContext) {
        invokeBindUnbindMethod(reference,  target, serviceInfo, bundleContext, false);
    }

    @SuppressWarnings("unchecked")
    private static List<ServiceInfo<?>> getMatchingServices(Class<?> type, BundleContext bundleContext, String filter) {
        List<ServiceInfo<?>> matchingServices = new ArrayList<>();
        try {
            ServiceReference[] references = bundleContext.getServiceReferences(type.getName(), filter);
            if (references != null) {
                for (ServiceReference<?> serviceReference : references) {
                    Object serviceInstance = bundleContext.getService(serviceReference);
                    Map<String, Object> serviceConfig = new HashMap<>();
                    String[] keys = serviceReference.getPropertyKeys();
                    for (String key : keys) {
                        serviceConfig.put(key, serviceReference.getProperty(key));
                    }
                    matchingServices.add(new ServiceInfo(serviceInstance, serviceConfig, serviceReference));
                }
            }
        } catch (InvalidSyntaxException ex) {
            // ignore
        }
        return matchingServices;
    }

    /**
     * Collects all references of any registered service that match with any of the exported interfaces of the given service registration
     * and are defined as DYNAMIC.
     * @param registeredServices Registered Services
     * @param registration Service registration
     * @return List of references
     */
    @SuppressWarnings("unchecked")
    public static List<ReferenceInfo<?>> getMatchingDynamicReferences(SortedSet<MockServiceRegistration> registeredServices,
            MockServiceRegistration<?> registration) {
        List<ReferenceInfo<?>> references = new ArrayList<>();
        for (MockServiceRegistration<?> existingRegistration : registeredServices) {
            @SuppressWarnings("null")
            OsgiMetadata metadata = OsgiMetadataUtil.getMetadata(existingRegistration.getService().getClass());
            if (metadata != null) {
                for (Reference reference : metadata.getReferences()) {
                    if (reference.isConstructorParameter()) {
                        continue;
                    }
                    if (reference.getPolicy() == ReferencePolicy.DYNAMIC) {
                        for (String serviceInterface : registration.getClasses()) {
                            if (StringUtils.equals(serviceInterface, reference.getInterfaceType())) {
                                references.add(new ReferenceInfo(existingRegistration, reference));
                            }
                        }
                    }
                }
            }
        }
        return references;
    }

    /**
     * Collects all references of any registered service that match with any of the exported interfaces of the given service registration
     * and are defined as STATIC + GREEDY.
     * @param registeredServices Registered Services
     * @param registration Service registration
     * @return List of references
     */
    @SuppressWarnings({ "unchecked", "null" })
    public static List<ReferenceInfo<?>> getMatchingStaticGreedyReferences(SortedSet<MockServiceRegistration> registeredServices,
            MockServiceRegistration<?> registration) {
        List<ReferenceInfo<?>> references = new ArrayList<>();
        for (MockServiceRegistration<?> existingRegistration : registeredServices) {
            OsgiMetadata metadata = OsgiMetadataUtil.getMetadata(existingRegistration.getService().getClass());
            if (metadata != null) {
                for (Reference reference : metadata.getReferences()) {
                    if (reference.getPolicy() == ReferencePolicy.STATIC && reference.getPolicyOption() == ReferencePolicyOption.GREEDY) {
                        for (String serviceInterface : registration.getClasses()) {
                            if (StringUtils.equals(serviceInterface, reference.getInterfaceType())) {
                                references.add(new ReferenceInfo(existingRegistration, reference));
                            }
                        }
                    }
                }
            }
        }
        return references;
    }

    static class ServiceInfo<T> {

        private final T serviceInstance;
        private final Map<String, Object> serviceConfig;
        private final ServiceReference<T> serviceReference;

        public ServiceInfo(T serviceInstance, Map<String, Object> serviceConfig, ServiceReference<T> serviceReference) {
            this.serviceInstance = serviceInstance;
            this.serviceConfig = serviceConfig;
            this.serviceReference = serviceReference;
        }

        public ServiceInfo(MockServiceRegistration<T> registration) {
            this.serviceInstance = registration.getService();
            this.serviceConfig = registration.getPropertiesAsMap();
            this.serviceReference = registration.getReference();
        }

        public T getServiceInstance() {
            return this.serviceInstance;
        }

        public Map<String, Object> getServiceConfig() {
            return this.serviceConfig;
        }

        public ServiceReference<T> getServiceReference() {
            return serviceReference;
        }

    }

    static class ReferenceInfo<T> {

        private final MockServiceRegistration<T> serviceRegistration;
        private final Reference reference;

        public ReferenceInfo(MockServiceRegistration<T> serviceRegistration, Reference reference) {
            this.serviceRegistration = serviceRegistration;
            this.reference = reference;
        }

        public MockServiceRegistration<T> getServiceRegistration() {
            return serviceRegistration;
        }

        public Reference getReference() {
            return reference;
        }

    }

}
