/**
 * 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.util.ArrayList;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.aries.blueprint.BlueprintConstants;
import org.apache.aries.blueprint.ExtendedBlueprintContainer;
import org.apache.aries.blueprint.ServiceProcessor;
import org.apache.aries.blueprint.di.AbstractRecipe;
import org.apache.aries.blueprint.di.CollectionRecipe;
import org.apache.aries.blueprint.di.MapRecipe;
import org.apache.aries.blueprint.di.Recipe;
import org.apache.aries.blueprint.di.Repository;
import org.apache.aries.blueprint.utils.JavaUtils;
import org.apache.aries.blueprint.utils.ReflectionUtils;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.blueprint.container.ComponentDefinitionException;
import org.osgi.service.blueprint.reflect.RefMetadata;
import org.osgi.service.blueprint.reflect.ServiceMetadata;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A <code>Recipe</code> to export services into the OSGi registry.
 *
 * @version $Rev: 990095 $, $Date: 2010-08-27 11:56:22 +0100 (Fri, 27 Aug 2010) $
 */
public class ServiceRecipe extends AbstractRecipe {

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

    private final ExtendedBlueprintContainer blueprintContainer;
    private final ServiceMetadata metadata;
    private final Recipe serviceRecipe;
    private final CollectionRecipe listenersRecipe;
    private final MapRecipe propertiesRecipe;
    private final List<Recipe> explicitDependencies;

    private Map properties;
    private final AtomicBoolean registered = new AtomicBoolean();
    private final AtomicReference<ServiceRegistration> registration = new AtomicReference<ServiceRegistration>();
    private Map registrationProperties;
    private List<ServiceListener> listeners;
    private volatile Object service;
    
    public ServiceRecipe(String name,
                         ExtendedBlueprintContainer blueprintContainer,
                         ServiceMetadata metadata,
                         Recipe serviceRecipe,
                         CollectionRecipe listenersRecipe,
                         MapRecipe propertiesRecipe,
                         List<Recipe> explicitDependencies) {
        super(name);
        this.prototype = false;
        this.blueprintContainer = blueprintContainer;
        this.metadata = metadata;
        this.serviceRecipe = serviceRecipe;
        this.listenersRecipe = listenersRecipe;
        this.propertiesRecipe = propertiesRecipe;
        this.explicitDependencies = explicitDependencies;
    }
    
    public Recipe getServiceRecipe() {
        return serviceRecipe;
    }

    public CollectionRecipe getListenersRecipe() {
        return listenersRecipe;
    }

    @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 (serviceRecipe != null) {
            recipes.add(serviceRecipe);
        }
        if (listenersRecipe != null) {
            recipes.add(listenersRecipe);
        }
        if (propertiesRecipe != null) {
            recipes.add(propertiesRecipe);
        }        
        recipes.addAll(getConstructorDependencies());        
        return recipes;
    }

    protected Object internalCreate() throws ComponentDefinitionException {
        ServiceRegistrationProxy proxy = new ServiceRegistrationProxy();
        addPartialObject(proxy);
        internalGetService(null, null); // null bundle means we don't want to retrieve the actual service when used with a ServiceFactory
        return proxy;
    }

    public boolean isRegistered() {
        return registered.get();
    }

    public void register() {
        if (registered.compareAndSet(false, true)) {
            createExplicitDependencies();
            
            Hashtable props = new Hashtable();
            if (properties == null) {
                properties = (Map) createRecipe(propertiesRecipe);
            }
            props.putAll(properties);
            if (metadata.getRanking() == 0) {
                props.remove(Constants.SERVICE_RANKING);
            } else {
                props.put(Constants.SERVICE_RANKING, metadata.getRanking());
            }
            String componentName = getComponentName();
            if (componentName != null) {
                props.put(BlueprintConstants.COMPONENT_NAME_PROPERTY, componentName);
            } else {
                props.remove(BlueprintConstants.COMPONENT_NAME_PROPERTY);
            }
            for (ServiceProcessor processor : blueprintContainer.getProcessors(ServiceProcessor.class)) {
                processor.updateProperties(new PropertiesUpdater(), props);
            }

            registrationProperties = props;

            Set<String> classes = getClasses();
            String[] classArray = classes.toArray(new String[classes.size()]);

            LOGGER.debug("Registering service {} with interfaces {} and properties {}",
                         new Object[] { name, classes, props });

            registration.set(blueprintContainer.registerService(classArray, new TriggerServiceFactory(), props));            
        }
    }

    public void unregister() {
        if (registered.compareAndSet(true, false)) {
            LOGGER.debug("Unregistering service {}", name);
            // This method needs to allow reentrance, so if we need to make sure the registration is
            // set to null before actually unregistering the service
            ServiceRegistration reg = registration.get();
            if (listeners != null) {
                LOGGER.debug("Calling listeners for service unregistration");
                for (ServiceListener listener : listeners) {
                    listener.unregister(service, registrationProperties);
                }
            }
            if (reg != null) {
                reg.unregister();
            }
            
            registration.compareAndSet(reg, null);
        }
    }

    protected ServiceReference getReference() {
    	ServiceRegistration reg = registration.get();
        if (reg == null) {
            throw new IllegalStateException("Service is not registered");
        } else {
            return reg.getReference();
        }
    }

    protected void setProperties(Dictionary props) {
    	ServiceRegistration reg = registration.get();
        if (reg == null) {
            throw new IllegalStateException("Service is not registered");
        } else {
            reg.setProperties(props);
            // TODO: set serviceProperties? convert somehow? should listeners be notified of this?
        }
    }


    protected Object internalGetService() {
        return internalGetService(blueprintContainer.getBundleContext().getBundle(), null);
    }

    /**
     * Create the service object.
     * We need to synchronize the access to the repository,
     * but not on this ServiceRecipe instance to avoid deadlock.
     * When using internalCreate(), no other lock but the on the repository
     * should be held.
     *
     * @param bundle
     * @param registration
     * @return
     */
    private Object internalGetService(Bundle bundle, ServiceRegistration registration) {
        LOGGER.debug("Retrieving service for bundle {} and service registration {}", bundle, registration);
        if (this.service == null) {
            synchronized (blueprintContainer.getRepository().getInstanceLock()) {
                if (this.service == null) {
                    createService();
                }
            }
        }
        
        Object service = this.service;
        // We need the real service ...
        if (bundle != null) {
        	if (service instanceof ServiceFactory) {
        		service = ((ServiceFactory) service).getService(bundle, registration);
        	}
        	if (service == null) {
        		throw new IllegalStateException("service is null");
        	}
        	// Check if the service actually implement all the requested interfaces
        	validateClasses(service);
        	// We're not really interested in the service, but perform some sanity checks nonetheless
        } else {
        	if (!(service instanceof ServiceFactory)) {
        		// Check if the service actually implement all the requested interfaces
        		validateClasses(service);
        	}
        }
        
        return service;
    }

    private void createService() {
        try {
            LOGGER.debug("Creating service instance");
            service = createRecipe(serviceRecipe);
            LOGGER.debug("Service created: {}", service);
            // When the service is first requested, we need to create listeners and call them
            if (listeners == null) {
                LOGGER.debug("Creating listeners");
                if (listenersRecipe != null) {
                    listeners = (List) createRecipe(listenersRecipe);
                } else {
                    listeners = Collections.emptyList();
                }
                LOGGER.debug("Listeners created: {}", listeners);
                if (registered.get()) {
                    LOGGER.debug("Calling listeners for initial service registration");
                    for (ServiceListener listener : listeners) {
                        listener.register(service, registrationProperties);
                    }
                } else {
                    LOGGER.debug("Calling listeners for initial service unregistration");
                    for (ServiceListener listener : listeners) {
                        listener.unregister(service, registrationProperties);
                    }
                }
            }
        } catch (RuntimeException e) {
            LOGGER.error("Error retrieving service from " + this, e);
            throw e;
        }
    }
    
    private void validateClasses(Object service) {
        // Check if the service actually implement all the requested interfaces
        if (metadata.getAutoExport() == ServiceMetadata.AUTO_EXPORT_DISABLED) {
            Set<String> allClasses = new HashSet<String>();
            ReflectionUtils.getSuperClasses(allClasses, service.getClass());
            ReflectionUtils.getImplementedInterfaces(allClasses, service.getClass());
            Set<String> classes = getClasses();
            classes.removeAll(allClasses);
            if (!classes.isEmpty()) {
                throw new ComponentDefinitionException("The service implementation does not implement the required interfaces: " + classes);
            }
        }
    }

    public Object getService(Bundle bundle, ServiceRegistration registration) {
        /** getService() can get called before registerService() returns with the registration object.
         *  So we need to set the registration object in case registration listeners call 
         *  getServiceReference(). 
         */
    	this.registration.compareAndSet(null, registration);
        return internalGetService(bundle, registration);
    }

    public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) {
        if (this.service instanceof ServiceFactory) {
            ((ServiceFactory) this.service).ungetService(bundle, registration, service);
        }
    }

    private Set<String> getClasses() {
        Set<String> classes;
        switch (metadata.getAutoExport()) {
            case ServiceMetadata.AUTO_EXPORT_INTERFACES:
                classes = ReflectionUtils.getImplementedInterfaces(new HashSet<String>(), internalGetService().getClass());
                break;
            case ServiceMetadata.AUTO_EXPORT_CLASS_HIERARCHY:
                classes = ReflectionUtils.getSuperClasses(new HashSet<String>(), internalGetService().getClass());
                break;
            case ServiceMetadata.AUTO_EXPORT_ALL_CLASSES:
                classes = ReflectionUtils.getSuperClasses(new HashSet<String>(), internalGetService().getClass());
                classes = ReflectionUtils.getImplementedInterfaces(classes, internalGetService().getClass());
                break;
            default:
                classes = new HashSet<String>(metadata.getInterfaces());
                break;
        }
        return classes;
    }

    private void createExplicitDependencies() {
        if (explicitDependencies != null) {
            for (Recipe recipe : explicitDependencies) {
                createRecipe(recipe);
            }
        }
    }
    
    private Object createRecipe(Recipe recipe) {
        String name = recipe.getName();
        Repository repo = blueprintContainer.getRepository();
        if (repo.getRecipe(name) != recipe) {
            repo.putRecipe(name, recipe);
        }
        return repo.create(name);
    }
   
    private String getComponentName() {
        if (metadata.getServiceComponent() instanceof RefMetadata) {
            RefMetadata ref = (RefMetadata) metadata.getServiceComponent();
            return ref.getComponentId();
        } else {
            return null;
        }
    }

    private class TriggerServiceFactory implements ServiceFactory {

        public Object getService(Bundle bundle, ServiceRegistration registration) {
            return ServiceRecipe.this.getService(bundle, registration);
        }

        public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) {
            ServiceRecipe.this.ungetService(bundle, registration, service);
        }

    }

    private class ServiceRegistrationProxy implements ServiceRegistration {

        public ServiceReference getReference() {
            return ServiceRecipe.this.getReference();
        }

        public void setProperties(Dictionary properties) {
            ServiceRecipe.this.setProperties(properties);
        }

        public void unregister() {
            throw new UnsupportedOperationException();
        }
    }

    private class PropertiesUpdater implements ServiceProcessor.ServicePropertiesUpdater {

        public String getId() {
            return metadata.getId();
        }

        public void updateProperties(Dictionary properties) {
            Hashtable table = JavaUtils.getProperties(ServiceRecipe.this.getReference());
            JavaUtils.copy(table, properties);
            ServiceRecipe.this.setProperties(table);
        }        
    }

}
