/*
 * 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.aries.blueprint.container;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicBoolean;

import net.sf.cglib.proxy.Dispatcher;
import net.sf.cglib.proxy.Enhancer;

import org.apache.aries.blueprint.BlueprintConstants;
import org.apache.aries.blueprint.ExtendedBlueprintContainer;
import org.apache.aries.blueprint.ExtendedReferenceListMetadata;
import org.apache.aries.blueprint.ExtendedServiceReferenceMetadata;
import org.apache.aries.blueprint.di.AbstractRecipe;
import org.apache.aries.blueprint.di.CollectionRecipe;
import org.apache.aries.blueprint.di.Recipe;
import org.apache.aries.blueprint.utils.BundleDelegatingClassLoader;
import org.apache.aries.blueprint.utils.ReflectionUtils;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.osgi.service.blueprint.container.ComponentDefinitionException;
import org.osgi.service.blueprint.container.ReifiedType;
import org.osgi.service.blueprint.reflect.ReferenceListener;
import org.osgi.service.blueprint.reflect.ReferenceMetadata;
import org.osgi.service.blueprint.reflect.ServiceReferenceMetadata;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Abstract class for service reference recipes.
 *
 * TODO: if we have a single interface (which is the standard behavior), then we should be able to get rid of
 *       the proxyClassloader and just use this interface classloader to define the proxy
 *
 * TODO: it is allowed to have no interface defined at all, which should result in an empty proxy
 *
 * @version $Rev$, $Date$
 */
public abstract class AbstractServiceReferenceRecipe extends AbstractRecipe implements ServiceListener, SatisfiableRecipe {

    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractServiceReferenceRecipe.class);

    protected final ExtendedBlueprintContainer blueprintContainer;
    protected final ServiceReferenceMetadata metadata;
    protected final CollectionRecipe listenersRecipe;
    protected final List<Recipe> explicitDependencies;
    protected final ClassLoader proxyClassLoader;
    protected final boolean optional;
    /** The OSGi filter for tracking references */
    protected final String filter;
    /** The list of listeners for this reference.  This list will be lazy created */
    protected List<Listener> listeners;

    private final List<ServiceReference> references = new ArrayList<ServiceReference>();
    private final AtomicBoolean started = new AtomicBoolean();
    private final AtomicBoolean satisfied = new AtomicBoolean();
    private SatisfactionListener satisfactionListener;
    private volatile ProxyFactory proxyFactory;

    protected AbstractServiceReferenceRecipe(String name,
                                             ExtendedBlueprintContainer blueprintContainer,
                                             ServiceReferenceMetadata metadata,
                                             CollectionRecipe listenersRecipe,
                                             List<Recipe> explicitDependencies) {
        super(name);
        this.prototype = false;
        this.blueprintContainer = blueprintContainer;
        this.metadata = metadata;
        this.listenersRecipe = listenersRecipe;
        this.explicitDependencies = explicitDependencies;
        
        
        this.proxyClassLoader = makeProxyClassLoader(blueprintContainer, metadata);

        this.optional = (metadata.getAvailability() == ReferenceMetadata.AVAILABILITY_OPTIONAL);
        this.filter = createOsgiFilter(metadata);
    }



    // Create a ClassLoader delegating to the bundle, but also being able to see our bundle classes
    // so that the created proxy can access cglib classes.
    // TODO: we should be able to get rid of this classloader when using JDK 1.4 proxies with a single interface
    //         (the case defined by the spec) and use the interface classloader instead
    private ClassLoader makeProxyClassLoader(
        final ExtendedBlueprintContainer blueprintContainer,
        ServiceReferenceMetadata metadata) {
      
      String typeName = metadata.getInterface();
      Class typeClass = metadata instanceof ExtendedServiceReferenceMetadata
                                ? ((ExtendedServiceReferenceMetadata) metadata).getRuntimeInterface() : null;
      if (typeName == null && typeClass == null) {
        return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
          public ClassLoader run() {
            return new BundleDelegatingClassLoader(blueprintContainer.getBundleContext().getBundle(),
                AbstractServiceReferenceRecipe.class.getClassLoader());
          }      
        });
      }
      
      final ClassLoader interfaceClassLoader;
      if (typeClass != null) {
          interfaceClassLoader = typeClass.getClassLoader();
      } else {
        try {
          Bundle clientBundle = blueprintContainer.getBundleContext().getBundle();
          interfaceClassLoader = clientBundle.loadClass(typeName).getClassLoader();
        } catch (ClassNotFoundException cnfe) {
          throw new ComponentDefinitionException("Unable to load class " + typeName + " from recipe " + this, cnfe);
        }
      }
      
      return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
        public ClassLoader run() {
          return new DualClassloader(interfaceClassLoader);
        }      
      });
    }

    private static class DualClassloader extends ClassLoader {
      DualClassloader(ClassLoader parent) {
        super(parent);
      }
      
      @Override
      protected Class<?> findClass(String name) throws ClassNotFoundException {
        return getClass().getClassLoader().loadClass(name);
      }

      @Override
      protected URL findResource(String name) {
        return getClass().getClassLoader().getResource(name);
      }
    }
    
    public CollectionRecipe getListenersRecipe() {
        return listenersRecipe;
    }

    public void start(SatisfactionListener listener) {
        if (listener == null) throw new NullPointerException("satisfactionListener is null");
        if (started.compareAndSet(false, true)) {
            try {
                satisfactionListener = listener;
                satisfied.set(optional);
                // Synchronized block on references so that service events won't interfere with initial references tracking
                // though this may not be sufficient because we don't control ordering of those events
                synchronized (references) {
                    blueprintContainer.getBundleContext().addServiceListener(this, getOsgiFilter());
                    ServiceReference[] references = blueprintContainer.getBundleContext().getServiceReferences(null, getOsgiFilter());
                    if (references != null) {
                        for (ServiceReference reference : references) {
                            this.references.add(reference);
                            track(reference);                           
                        }
                        satisfied.set(optional || !this.references.isEmpty());
                    }
                    LOGGER.debug("Found initial references {} for OSGi service {}", references, getOsgiFilter());
                }
            } catch (InvalidSyntaxException e) {
                throw new ComponentDefinitionException(e);
            }
        }
    }

    public void stop() {
        if (started.compareAndSet(true, false)) {
            synchronized (references) {
                blueprintContainer.getBundleContext().removeServiceListener(this);
                doStop();
                for (Iterator<ServiceReference> it = references.iterator(); it.hasNext();) {
                    ServiceReference ref = it.next();
                    it.remove();
                    untrack(ref);
                }
                satisfied.set(false);
            }
        }
    }

    protected void doStop() {
    }

    protected boolean isStarted() {
        return started.get();
    }

    public boolean isSatisfied() {
        return satisfied.get();
    }

    @Override
    public List<Recipe> getConstructorDependencies() {
        List<Recipe> recipes = new ArrayList<Recipe>();
        if (explicitDependencies != null) {
            recipes.addAll(explicitDependencies);
        }
        return recipes;
    }
    
    public List<Recipe> getDependencies() {
        List<Recipe> recipes = new ArrayList<Recipe>();
        if (listenersRecipe != null) {
            recipes.add(listenersRecipe);
        }
        recipes.addAll(getConstructorDependencies());
        return recipes;
    }

    public String getOsgiFilter() {
        return filter;
    }

    protected void createListeners() {
        try {
            if (listenersRecipe != null) {
                List<Listener> listeners = (List<Listener>) listenersRecipe.create();
                for (Listener listener : listeners) {
                    List<Class> cl = new ArrayList<Class>();
                    if (metadata instanceof ExtendedServiceReferenceMetadata && ((ExtendedServiceReferenceMetadata) metadata).getRuntimeInterface() != null) {
                        cl.add(((ExtendedServiceReferenceMetadata) metadata).getRuntimeInterface());
                    } else if (metadata.getInterface() != null) {
                        cl.addAll(loadAllClasses(Collections.singletonList(metadata.getInterface())));
                    } else {
                        cl.add(Object.class);
                    }
                    listener.init(cl);
                }
                this.listeners = listeners;
            } else {
                this.listeners = Collections.emptyList();
            }
        } catch (ClassNotFoundException e) {
            throw new ComponentDefinitionException(e);
        }
    }

    protected List<Class> loadAllClasses(Iterable<String> interfaceNames) throws ClassNotFoundException {
        List<Class> classes = new ArrayList<Class>();
        for (String name : interfaceNames) {
            Class clazz = loadClass(name);
            classes.add(clazz);
        }
        return classes;
    }

    protected ReifiedType loadType(String typeName, ClassLoader fromClassLoader) {
        if (typeName == null) {
            return null;
        }
        try {
            // this method is overriden to use the blueprint container directly
            // because proxies can be created outside of the recipe creation which
            // would lead to an exception because the context is not set
            // TODO: consider having the context as a property on the recipe rather than a thread local
            return GenericType.parse(typeName, fromClassLoader != null ? fromClassLoader : blueprintContainer);
        } catch (ClassNotFoundException e) {
            throw new ComponentDefinitionException("Unable to load class " + typeName + " from recipe " + this, e);
        }
    }


    protected Object createProxy(final Callable<Object> dispatcher, Set<Class> interfaces) throws Exception {
        if (!interfaces.iterator().hasNext()) {
            return new Object();
        } else {
            return getProxyFactory().createProxy(proxyClassLoader, toClassArray(interfaces), dispatcher);
        }
    }

    protected synchronized ProxyFactory getProxyFactory() throws ClassNotFoundException {
        if (proxyFactory == null) {
            boolean proxyClass = false;
            if (metadata instanceof ExtendedServiceReferenceMetadata) {
                proxyClass = (((ExtendedServiceReferenceMetadata) metadata).getProxyMethod() & ExtendedServiceReferenceMetadata.PROXY_METHOD_CLASSES) != 0;
            }
            if (!proxyClass) {
                Set<Class> interfaces = new HashSet<Class>();
                if (metadata.getInterface() != null) {
                    interfaces.add(loadClass(metadata.getInterface()));
                }
                if (metadata instanceof ExtendedReferenceListMetadata
                            && ((ExtendedServiceReferenceMetadata) metadata).getRuntimeInterface() != null) {
                        interfaces.add(((ExtendedServiceReferenceMetadata) metadata).getRuntimeInterface());
                    }
                for (Class cl : interfaces) {
                    if (!cl.isInterface()) {
                        throw new ComponentDefinitionException("A class " + cl.getName() + " was found in the interfaces list, but class proxying is not allowed by default. The ext:proxy-method='classes' attribute needs to be added to this service reference.");
                    }
                }
            }
            try {
                // Try load load a cglib class (to make sure it's actually available
                // then create the cglib factory
                getClass().getClassLoader().loadClass("net.sf.cglib.proxy.Enhancer");
                proxyFactory = new CgLibProxyFactory();
            } catch (Throwable t) {
                if (proxyClass) {
                    throw new ComponentDefinitionException("Class proxying has been enabled but cglib can not be used", t);
                }
                proxyFactory = new JdkProxyFactory();
            }
        }
        return proxyFactory;
    }

    public void serviceChanged(ServiceEvent event) {
        int eventType = event.getType();
        ServiceReference ref = event.getServiceReference();
        switch (eventType) {
            case ServiceEvent.REGISTERED:
                serviceAdded(ref);
                break;
            case ServiceEvent.MODIFIED:
                serviceModified(ref);
                break;
            case ServiceEvent.UNREGISTERING:
                serviceRemoved(ref);
                break;
        }
    }

    private void serviceAdded(ServiceReference ref) {
        LOGGER.debug("Tracking reference {} for OSGi service {}", ref, getOsgiFilter());
        synchronized (references) {
            references.add(ref);
        }
        track(ref);
        setSatisfied(true);
    }

    private void serviceModified(ServiceReference ref) {
        // ref must be in references and must be satisfied
        track(ref);
    }

    private void serviceRemoved(ServiceReference ref) {
        LOGGER.debug("Untracking reference {} for OSGi service {}", ref, getOsgiFilter());
        boolean removed;
        boolean satisfied;
        synchronized (references) {
            removed = references.remove(ref);
            satisfied = optional || !references.isEmpty();
        }
        if (removed) {
            untrack(ref);
        }
        setSatisfied(satisfied);
    }

    protected void setSatisfied(boolean s) {
        // This check will ensure an atomic comparision and set
        // so that it will only be true if the value actually changed
        if (satisfied.getAndSet(s) != s) {
            LOGGER.debug("Service reference with filter {} satisfied {}", getOsgiFilter(), this.satisfied);
            this.satisfactionListener.notifySatisfaction(this);
        }
    }

    protected abstract void track(ServiceReference reference);

    protected abstract void untrack(ServiceReference reference);

    protected abstract void retrack();

    protected void updateListeners() {  
        if (references.isEmpty()) {
            unbind(null, null);
        } else {
            retrack();
        }
    }
    
    protected void bind(ServiceReference reference, Object service) {
        if (listeners != null) {    
            for (Listener listener : listeners) {
                if (listener != null) {
                    listener.bind(reference, service);
                }
            } 
        }
    }
    
    protected void unbind(ServiceReference reference, Object service) {
        if (listeners != null) {    
            for (Listener listener : listeners) {
                if (listener != null) {
                    listener.unbind(reference, service);
                }
            } 
        }
    }
    
    public List<ServiceReference> getServiceReferences() {
        synchronized (references) {
            return new ArrayList<ServiceReference>(references);
        }
    }

    public ServiceReference getBestServiceReference() {
        synchronized (references) {
            int length = references.size();
            if (length == 0) { /* if no service is being tracked */
                return null;
            }
            int index = 0;
            if (length > 1) { /* if more than one service, select highest ranking */
                int maxRanking = Integer.MIN_VALUE;
                long minId = Long.MAX_VALUE;
                for (int i = 0; i < length; i++) {
                    Object property = references.get(i).getProperty(Constants.SERVICE_RANKING);
                    int ranking = (property instanceof Integer) ? (Integer) property : 0;
                    long id = (Long) references.get(i).getProperty(Constants.SERVICE_ID);
                    if ((ranking > maxRanking) || (ranking == maxRanking && id < minId)) {
                        index = i;
                        maxRanking = ranking;
                        minId = id;
                    }
                }
            }
            return references.get(index);
        }
    }

    public static class Listener {

        private static final Logger LOGGER = LoggerFactory.getLogger(Listener.class);

        private Object listener;
        private ReferenceListener metadata;
        private ExtendedBlueprintContainer blueprintContainer;

        private Set<Method> bindMethodsReference = new HashSet<Method>();
        private Set<Method> bindMethodsObjectProp = new HashSet<Method>();
        private Set<Method> bindMethodsObject = new HashSet<Method>();
        private Set<Method> unbindMethodsReference = new HashSet<Method>();
        private Set<Method> unbindMethodsObject = new HashSet<Method>();
        private Set<Method> unbindMethodsObjectProp = new HashSet<Method>();

        public void setListener(Object listener) {
            this.listener = listener;
        }

        public void setMetadata(ReferenceListener metadata) {
            this.metadata = metadata;
        }

        public void setBlueprintContainer(ExtendedBlueprintContainer blueprintContainer) {
            this.blueprintContainer = blueprintContainer;
        }
        
        public void init(Collection<Class> classes) {
            Set<Class> clazzes = new HashSet<Class>(classes);
            clazzes.add(Object.class);
            Class listenerClass = listener.getClass();
            String bindName = metadata.getBindMethod();
            if (bindName != null) {
                bindMethodsReference.addAll(ReflectionUtils.findCompatibleMethods(listenerClass, bindName, new Class[] { ServiceReference.class }));
                for (Class clazz : clazzes) {
                    bindMethodsObject.addAll(ReflectionUtils.findCompatibleMethods(listenerClass, bindName, new Class[] { clazz }));
                    bindMethodsObjectProp.addAll(ReflectionUtils.findCompatibleMethods(listenerClass, bindName, new Class[] { clazz, Map.class }));
                }
                if (bindMethodsReference.size() + bindMethodsObject.size() + bindMethodsObjectProp.size() == 0) {
                    throw new ComponentDefinitionException("No matching methods found for listener bind method: " + bindName);
                }
            }
            String unbindName = metadata.getUnbindMethod();
            if (unbindName != null) {
                unbindMethodsReference.addAll(ReflectionUtils.findCompatibleMethods(listenerClass, unbindName, new Class[] { ServiceReference.class }));
                for (Class clazz : clazzes) {
                    unbindMethodsObject.addAll(ReflectionUtils.findCompatibleMethods(listenerClass, unbindName, new Class[] { clazz }));
                    unbindMethodsObjectProp.addAll(ReflectionUtils.findCompatibleMethods(listenerClass, unbindName, new Class[] { clazz, Map.class }));
                }
                if (unbindMethodsReference.size() + unbindMethodsObject.size() + unbindMethodsObjectProp.size() == 0) {
                    throw new ComponentDefinitionException("No matching methods found for listener unbind method: " + unbindName);
                }
            }
        }

        public void bind(ServiceReference reference, Object service) {
            invokeMethods(bindMethodsReference, bindMethodsObject, bindMethodsObjectProp, reference, service);
        }

        public void unbind(ServiceReference reference, Object service) {
            invokeMethods(unbindMethodsReference, unbindMethodsObject, unbindMethodsObjectProp, reference, service);
        }

        private void invokeMethods(Set<Method> referenceMethods, Set<Method> objectMethods, Set<Method> objectPropMethods, ServiceReference reference, Object service) {
            for (Method method : referenceMethods) {
                try {
                    ReflectionUtils.invoke(blueprintContainer.getAccessControlContext(), 
                                           method, listener, reference);
                } catch (Exception e) {
                    LOGGER.error("Error calling listener method " + method, e);
                }
            }
            for (Method method : objectMethods) {
                try {
                    ReflectionUtils.invoke(blueprintContainer.getAccessControlContext(), 
                                           method, listener, service);
                } catch (Exception e) {
                    LOGGER.error("Error calling listener method " + method, e);
                }
            }
            Map<String, Object> props = null;
            for (Method method : objectPropMethods) {
                if (props == null) {
                    props = new HashMap<String, Object>();
                    if (reference != null) {
                        for (String name : reference.getPropertyKeys()) {
                            props.put(name, reference.getProperty(name));
                        }
                    }
                }
                try {
                    ReflectionUtils.invoke(blueprintContainer.getAccessControlContext(), 
                                           method, listener, service, props);
                } catch (Exception e) {
                    LOGGER.error("Error calling listener method " + method, e);
                }
            }
        }
    }

    /**
     * Create the OSGi filter corresponding to the ServiceReferenceMetadata constraints
     *
     * @param metadata the service reference metadata
     * @return the OSGi filter
     */
    private static String createOsgiFilter(ServiceReferenceMetadata metadata) {
        List<String> members = new ArrayList<String>();
        // Handle filter
        String flt = metadata.getFilter();
        if (flt != null && flt.length() > 0) {
            if (!flt.startsWith("(")) {
                flt = "(" + flt + ")";
            }
            members.add(flt);
        }
        // Handle interfaces
        String interfaceName = metadata.getInterface();
        if (metadata instanceof ExtendedServiceReferenceMetadata && ((ExtendedServiceReferenceMetadata) metadata).getRuntimeInterface() != null) {
            interfaceName = ((ExtendedServiceReferenceMetadata) metadata).getRuntimeInterface().getName();
        }
        if (interfaceName != null && interfaceName.length() > 0) {
            members.add("(" + Constants.OBJECTCLASS + "=" + interfaceName + ")");
        }
        // Handle component name
        String componentName = metadata.getComponentName();
        if (componentName != null && componentName.length() > 0) {
            members.add("(" + BlueprintConstants.COMPONENT_NAME_PROPERTY + "=" + componentName + ")");
        }
        // Create filter
        if (members.isEmpty()) {
            throw new IllegalStateException("No constraints were specified on the service reference");
        }
        if (members.size() == 1) {
            return members.get(0);
        }
        StringBuilder sb = new StringBuilder("(&");
        for (String member : members) {
            sb.append(member);
        }
        sb.append(")");
        return sb.toString();
    }

    private static Class[] getInterfaces(Class[] classes) {
        Set<Class> interfaces = new HashSet<Class>();
        for (Class clazz : classes) {
            if (clazz.isInterface()) {
                interfaces.add(clazz);
            }
        }
        return toClassArray(interfaces);
    }

    private static Class[] toClassArray(Set<Class> classes) {
        return classes.toArray(new Class [classes.size()]);
    }

    public static interface ProxyFactory {

        public Object createProxy(ClassLoader classLoader, Class[] classes, Callable<Object> dispatcher);

    }

    public static class JdkProxyFactory implements ProxyFactory {

        public Object createProxy(final ClassLoader classLoader, final Class[] classes, final Callable<Object> dispatcher) {
            return Proxy.newProxyInstance(classLoader, getInterfaces(classes), new InvocationHandler() {
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    try {
                        return method.invoke(dispatcher.call(), args);
                    } catch (InvocationTargetException ite) {
                      throw ite.getTargetException();
                    }
                }
            });
        }

    }

    public static class CgLibProxyFactory implements ProxyFactory {

        public Object createProxy(final ClassLoader classLoader, final Class[] classes, final Callable<Object> dispatcher) {
            Enhancer e = new Enhancer();
            e.setClassLoader(classLoader);
            e.setSuperclass(getTargetClass(classes));
            e.setInterfaces(getInterfaces(classes));
            e.setInterceptDuringConstruction(false);
            e.setCallback(new Dispatcher() {
                public Object loadObject() throws Exception {
                    return dispatcher.call();
                }
            });
            e.setUseFactory(false);
            return e.create();
        }

        protected Class<?> getTargetClass(Class<?>[] interfaceNames) {
            // Only allow class proxying if specifically asked to
            Class<?> root = Object.class;
            for (Class<?> clazz : interfaceNames) {
                if (!clazz.isInterface()) {
                    if (root.isAssignableFrom(clazz)) {
                        root = clazz;
                    } else if (clazz.isAssignableFrom(root)) {
                        //nothing to do, root is correct
                    } else {
                        throw new ComponentDefinitionException("Classes " + root.getClass().getName() + " and " + clazz.getName() + " are not in the same hierarchy");
                    }
                }
            }
            return root;
        }

    }

}
