/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.felix.dm.runtime;

import java.lang.reflect.Method;
import java.util.AbstractSet;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.felix.dm.Component;
import org.apache.felix.dm.Dependency;
import org.apache.felix.dm.DependencyManager;
import org.osgi.framework.Bundle;

/**
 * This class implements a <code>java.util.Set</code> which acts as a service factory.
 * When a <code>Service</annotation> contains a <code>factory</code> attribute, this class is provided
 * into the OSGi registry with a <code>dm.factory.name</code> service property. So, another factory component
 * may be injected with this Set. And each time a Dictionary configuration is registered in the Set,
 * then a new Service instance will be instantiated, and will be provided with the Dictionary passed to the
 * Service instance.
 * 
 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
 */
@SuppressWarnings( { "unchecked" })
public class FactorySet extends AbstractSet<Dictionary>
{
    /**
     * The actual Service instance that is allocated for each dictionaries added in this Set.
     */
    private Object m_impl;

    /**
     * The Service provided in the OSGi registry.
     */
    private final String[] m_provide;

    /**
     * The properties to be provided by the Service.
     */
    private final Dictionary m_serviceProperties;

    /**
     * The configure Service callback used to pass configuration added in this Set.
     */
    private final String m_configure;

    /**
     * The map between our Dictionaries and corresponding Service instances.
     */
    private final ConcurrentHashMap<ServiceKey, Object> m_services = new ConcurrentHashMap<ServiceKey, Object>();

    /**
     * The list of Dependencies which are applied in the Service.
     */
    private MetaData m_srvMeta;

    /**
     * The list of Dependencies which are applied in the Service.
     */
    private List<MetaData> m_depsMeta;

    /**
     * The DependencyManager which is used to create Service instances.
     */
    private DependencyManager m_dm;

    /**
     * This class is used to serialize concurrent method calls, and allow to leave our methods unsynchronized.
     * This is required because some of our methods may invoke some Service callbacks, which must be called outside 
     * synchronized block (in order to avoid potential dead locks).
     */
    private SerialExecutor m_serialExecutor = new SerialExecutor();

    /**
     * Flag used to check if our service is Active.
     */
    private volatile boolean m_active;

    /**
     * The bundle containing the Service annotated with the factory attribute.
     */
    private Bundle m_bundle;

    /**
     * Flag used to check if a service is being created
     */
    private final static Object SERVICE_CREATING = new Object();

    /**
     * When a Dictionary is registered in a factory Set, we use this special 
     * property key, whose value may provide the instance to use when
     * creating a service.
     */
    private final static String DM_FACTORY_INSTANCE = "dm.factory.instance";

    /**
     * This class wraps <tt>Dictionary</tt>, allowing to store the dictionary into a Map, using
     * reference-equality in place of object-equality when getting the Dictionary from the Map.
     */
    private static class ServiceKey
    {
        private Dictionary m_dictionary;

        public ServiceKey(Dictionary dictionary)
        {
            m_dictionary = dictionary;
        }

        Dictionary getDictionary()
        {
            return m_dictionary;
        }

        @Override
        public boolean equals(Object that)
        {
            return that instanceof ServiceKey ? (((ServiceKey) that).getDictionary() == m_dictionary)
                : false;
        }

        @Override
        public int hashCode()
        {
            return System.identityHashCode(m_dictionary);
        }

        @Override
        public String toString()
        {
            return Dictionary.class.getName() + "@" + System.identityHashCode(m_dictionary);
        }
    }

    /**
     * Sole constructor.
     * @param b the bundle containing the Service annotated with the factory attribute
     * @param impl The Service implementation class
     * @param serviceProperties The Service properties
     * @param provides The Services provided by this Service
     * @param factoryConfigure The configure callback invoked in order to pass configurations added in this Set.
     */
    public FactorySet(Bundle b, MetaData srvMeta, List<MetaData> depsMeta)
    {
        m_serviceProperties = srvMeta.getDictionary(Params.properties, null);
        m_provide = srvMeta.getStrings(Params.provides, null);
        m_configure = srvMeta.getString(Params.factoryConfigure, null);
        m_bundle = b;
        m_srvMeta = srvMeta;
        m_depsMeta = depsMeta;
    }

    /**
     * Our Service is starting. 
     */
    public void start(Component c)
    {
        m_active = true;
        m_dm = c.getDependencyManager();
    }

    /**
     * Our Service is stopping: we have to remove all Service instances that we have created.
     */
    public void stop()
    {
        try
        {
            clear();
        }
        finally
        {
            m_active = false;
        }
    }

    /**
     * Create or Update a Service.
     */
    @Override
    @SuppressWarnings("synthetic-access")
    public boolean add(final Dictionary configuration)
    {
        // Check parameter validity
        if (configuration == null)
        {
            throw new NullPointerException("configuration parameter can't be null");
        }

        // Check if our service is running.
        checkServiceAvailable();

        // Check if service is being created
        ServiceKey serviceKey = new ServiceKey(configuration);
        boolean creating = false;
        synchronized (this)
        {
            if (!m_services.containsKey(serviceKey))
            {
                m_services.put(serviceKey, SERVICE_CREATING);
                creating = true;
            }
            // Create or Update the Service.
            m_serialExecutor.enqueue(new Runnable()
            {
                public void run()
                {
                    doAdd(configuration);
                }
            });
        }

        m_serialExecutor.execute();
        return creating;
    }

    /**
     * Another Service wants to remove an existing Service.
     * This method is not synchronized but uses a SerialExecutor for serializing concurrent method call.
     * (This avoid potential dead locks, especially when Service callback methods are invoked).
     */
    @Override
    @SuppressWarnings("synthetic-access")
    public boolean remove(final Object configuration)
    {
        // Check parameter validity.
        if (configuration == null)
        {
            throw new NullPointerException("configuration parameter can't be null");
        }
        if (!(configuration instanceof Dictionary))
        {
            throw new IllegalArgumentException("configuration must be an instance of a Dictionary");
        }

        // Check if our service is active.
        checkServiceAvailable();

        // Check if service is created (or creating)
        boolean found = m_services.containsKey(new ServiceKey((Dictionary) configuration));
        if (found)
        {
            // Create or Update the Service.
            m_serialExecutor.enqueue(new Runnable()
            {
                public void run()
                {
                    doRemove((Dictionary) configuration);
                }
            });
            m_serialExecutor.execute();
        }
        return found;
    }

    /**
     * Another Service wants to remove all existing Services.
     * This method is not synchronized but uses a SerialExecutor for serializing concurrent method call.
     * (This avoid potential dead locks, especially when Service callback methods are invoked).
     */
    @Override
    @SuppressWarnings("synthetic-access")
    public void clear()
    {
        if (!m_active)
        {
            return;
        }

        // Create or Update the Service.
        m_serialExecutor.enqueue(new Runnable()
        {
            public void run()
            {
                doClear();
            }
        });
        m_serialExecutor.execute();
    }

    /**
     * returns the list of active Service instances configurations.
     */
    @Override
    public Iterator<Dictionary> iterator()
    {
        throw new UnsupportedOperationException(
            "iterator method is not supported by DependencyManager Set's service factories");
    }

    @Override
    public String toString()
    {
        return FactorySet.class.getName() + "(" + m_services.size() + " active instances)";
    }

    /**
     * Returns the number of active Service instances.
     */
    @Override
    public int size()
    {
        if (!m_active)
        {
            return 0;
        }
        return m_services.size();
    }

    /**
     * Checks if our Service is available (we are not stopped").
     */
    private void checkServiceAvailable()
    {
        if (!m_active)
        {
            throw new IllegalStateException("Service not available");
        }
    }

    /**
     * Add or create a new Service instance, given its configuration. This method is invoked by the
     * SerialExecutor, hence it's thread safe and we'll invoke Service's callbacks without being
     * synchronized (hence this will avoid potential dead locks).
     */
    private void doAdd(Dictionary configuration)
    {
        // Check if the service exists.
        ServiceKey serviceKey = new ServiceKey(configuration);
        Object service = m_services.get(serviceKey);
        if (service == null || service == SERVICE_CREATING)
        {
            try
            {
                // Create the Service / impl, unless it is explicitly provided from the
                // configuration (using the specific key "dm.factory.instance").
                Component s = m_dm.createComponent();
                Class implClass = m_bundle.loadClass(m_srvMeta.getString(Params.impl));
                Object impl = configuration.get(DM_FACTORY_INSTANCE);
                if (impl == null)
                {
                    String factoryMethod = m_srvMeta.getString(Params.factoryMethod, null);
                    if (factoryMethod == null)
                    {
                        m_impl = implClass.newInstance();
                    }
                    else
                    {
                        Method m = implClass.getDeclaredMethod(factoryMethod);
                        m.setAccessible(true);
                        m_impl = m.invoke(null);
                    }
                }
                else
                {
                    m_impl = impl;
                }

                // Invoke "configure" callback
                if (m_configure != null)
                {
                    invokeConfigure(m_impl, m_configure, configuration);
                }

                // Create Service
                s.setImplementation(m_impl);
                if (m_provide != null)
                {
                     // Merge service properties with the configuration provided by the factory.
                    Dictionary serviceProperties = mergeSettings(m_serviceProperties, configuration);
                    s.setInterface(m_provide, serviceProperties);
                }

                s.setComposition(m_srvMeta.getString(Params.composition, null));
                ServiceLifecycleHandler lfcleHandler = new ServiceLifecycleHandler(s, m_bundle, m_dm,
                    m_srvMeta, m_depsMeta);
                // The dependencies will be plugged by our lifecycle handler.
                s.setCallbacks(lfcleHandler, "init", "start", "stop", "destroy");

                // Adds dependencies (except named dependencies, which are managed by the lifecycle handler).
                for (MetaData dependency: m_depsMeta)
                {
                    String name = dependency.getString(Params.name, null);
                    if (name == null)
                    {
                        DependencyBuilder depBuilder = new DependencyBuilder(dependency);
                        Log.instance().info("ServiceLifecycleHandler.init: adding dependency %s into service %s",
                                            dependency, m_srvMeta);
                        Dependency d = depBuilder.build(m_bundle, m_dm, false);
                        s.add(d);
                    }
                }

                // Register the Service instance, and keep track of it.
                Log.instance().info("ServiceFactory: created service %s", m_srvMeta);
                m_dm.add(s);
                m_services.put(serviceKey, s);
            }
            catch (Throwable t)
            {
                // Make sure the SERVICE_CREATING flag is also removed
                m_services.remove(serviceKey);
                Log.instance().error("ServiceFactory: could not instantiate service %s",
                                     t, m_srvMeta);
            }
        }
        else
        {
            // Reconfigure an already existing Service.
            if (m_configure != null)
            {
                Log.instance().info("ServiceFactory: updating service %s", m_impl);
                invokeConfigure(m_impl, m_configure, configuration);
            }

            // Update service properties
            if (m_provide != null)
            {
                Dictionary settings = mergeSettings(m_serviceProperties, configuration);
                ((Component) service).setServiceProperties(settings);
            }
        }
    }

    private void doRemove(Dictionary configuraton)
    {
        Log.instance().info("ServiceFactory: removing service %s", m_srvMeta);
        ServiceKey serviceKey = new ServiceKey(configuraton);
        Object service = m_services.remove(serviceKey);
        if (service != null && service != SERVICE_CREATING)
        {
            m_dm.remove((Component) service);
        }
    }

    private void doClear()
    {
        try
        {
            for (Object service: m_services.values())
            {
                if (service instanceof Component)
                {
                    m_dm.remove((Component) service);
                }
            }
        }
        finally
        {
            m_services.clear();
        }
    }

    /**
     * Merge factory configuration settings with the service properties. The private factory configuration 
     * settings are ignored. A factory configuration property is private if its name starts with a dot (".").
     * 
     * @param serviceProperties
     * @param factoryConfiguration
     * @return
     */
    private Dictionary mergeSettings(Dictionary serviceProperties, Dictionary factoryConfiguration)
    {
        Dictionary props = new Hashtable();

        if (serviceProperties != null)
        {
            Enumeration keys = serviceProperties.keys();
            while (keys.hasMoreElements())
            {
                Object key = keys.nextElement();
                Object val = serviceProperties.get(key);
                props.put(key, val);
            }
        }

        Enumeration keys = factoryConfiguration.keys();
        while (keys.hasMoreElements())
        {
            Object key = keys.nextElement();
            if (!key.toString().startsWith("."))
            {
                // public properties are propagated
                Object val = factoryConfiguration.get(key);
                props.put(key, val);
            }
        }
        return props;
    }

    /**
     * Invokes the configure callback method on the service instance implemenatation.
     * @param impl
     * @param configure
     * @param config
     */
    private void invokeConfigure(Object impl, String configure, Dictionary config)
    {
        try
        {
            InvocationUtil.invokeCallbackMethod(impl, configure,
                                                new Class[][] { { Dictionary.class } },
                                                new Object[][] { { config } });
        }

        catch (Throwable t)
        {
            if (t instanceof RuntimeException)
            {
                throw (RuntimeException) t;
            }
            else
            {
                throw new RuntimeException("Could not invoke method " + configure
                                           + " on object " + impl, t);
            }
        }
    }
}
