/*
 * 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.helper.ComponentServiceObjectsHelper;
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.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<>();
        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);
                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
     * @param parameterType Parameter type
     * @param reference Reference
     * @param componentContext Component context
     * @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) throws InstantiationException, IllegalAccessException {
        // get matching service references
        List<ServiceInfo> matchingServices = getMatchingServices(reference.getInterfaceTypeAsClass(),
                componentContext.getBundleContext(), reference.getTarget());

        if (matchingServices.isEmpty() && !reference.isCardinalityOptional()) {
            throw new ReferenceViolationException("Unable to inject mandatory reference '" + reference.getName() + "' 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() + "' 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 (classEqualsOrSuper(parameterType, reference.getInterfaceTypeAsClass())) {
                return firstServiceInfo.map(ServiceInfo::getServiceInstance);
            }

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

        // no match
        return null;
    }

    @SuppressWarnings("unchecked")
    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() + "' for class " + targetClass.getName() + " : no matching services were found.");
            }
            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() + "' for class " +  targetClass.getName());
        }

        if (StringUtils.isNotEmpty(methodName) && serviceInfo != null) {
            ComponentServiceObjectsHelper helper = new ComponentServiceObjectsHelper(bundleContext);

            // 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[] { helper.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] = helper.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() + "' 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;
                }
            }
        }

    }

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

    private static List<ServiceInfo> getMatchingServices(Class<?> type, BundleContext bundleContext, String filter) {
        List<ServiceInfo> matchingServices = new ArrayList<ServiceInfo>();
        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, Object>();
                    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
     */
    public static List<ReferenceInfo> getMatchingDynamicReferences(SortedSet<MockServiceRegistration> registeredServices,
            MockServiceRegistration<?> registration) {
        List<ReferenceInfo> references = new ArrayList<ReferenceInfo>();
        for (MockServiceRegistration existingRegistration : registeredServices) {
            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 (classEqualsOrSuper(serviceInterface, reference.getInterfaceTypeAsClass())) {
                                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
     */
    public static List<ReferenceInfo> getMatchingStaticGreedyReferences(SortedSet<MockServiceRegistration> registeredServices,
            MockServiceRegistration<?> registration) {
        List<ReferenceInfo> references = new ArrayList<ReferenceInfo>();
        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 (classEqualsOrSuper(serviceInterface, reference.getInterfaceTypeAsClass())) {
                                references.add(new ReferenceInfo(existingRegistration, reference));
                            }
                        }
                    }
                }
            }
        }
        return references;
    }

    /**
     * Checks if the given class is the same as the expected class, or the expected class is a supertype of it.
     * @param givenClassName Given class
     * @param expectedClassName Expected class
     * @return true if classes match
     */
    private static boolean classEqualsOrSuper(String givenClassName, Class<?> expectedClass) {
        Class<?> givenClass;
        try {
            givenClass = Class.forName(givenClassName);
        }
        catch (ClassNotFoundException ex) {
            throw new RuntimeException("Untable to get class for " + givenClassName + ": " + ex.getMessage(), ex);
        }
        return classEqualsOrSuper(givenClass, expectedClass);
    }

    /**
     * Checks if the given class is the same as the expected class, or the expected class is a supertype of it.
     * @param givenClassName Given class
     * @param expectedClassName Expected class
     * @return true if classes match
     */
    private static boolean classEqualsOrSuper(Class<?> givenClass, Class<?> expectedClass) {
        return expectedClass.isAssignableFrom(givenClass);
    }


    static class ServiceInfo {

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

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

        @SuppressWarnings("unchecked")
        public ServiceInfo(MockServiceRegistration registration) {
            this.serviceInstance = registration.getService();
            this.serviceConfig = registration.getPropertiesAsMap();
            this.serviceReference = registration.getReference();
        }

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

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

        public ServiceReference getServiceReference() {
            return serviceReference;
        }

    }

    static class ReferenceInfo {

        private final MockServiceRegistration serviceRegistration;
        private final Reference reference;

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

        public MockServiceRegistration getServiceRegistration() {
            return serviceRegistration;
        }

        public Reference getReference() {
            return reference;
        }

    }

}
