/*
 * 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.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

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

/**
 * Caution: this class *MUST* be immutable, because it may be shared between Aspects/Adapters 
 * and concrete Aspect/Adapter instance.
 * 
 * This class allows Services to configure dynamically their dependency filters from their init() method.
 * Basically, this class acts as a service implementation lifecycle handler. When we detect that the Service is
 * called in its init() method, and if init() returns a Map, then the Map is assumed to contain
 * dependency filters, which will be applied to all named dependencies. The Map optionally returned by
 * Service's init method may contain the following keys:
 * <ul>
 *   <li>name.filter: the value must be a valid OSGi filter, and the "name" prefix must match a ServiceDependency 
 *   name attribute</li>
 *   <li>name.required: the value is a boolean ("true"|"false") and the "name" prefix must match a 
 *   ServiceDependency name attribute</li>
 * </ul>
 * 
 * <p>Dependencies which provide a name attribute will be activated after the init method returns. Other
 * dependencies are injected before the init method.
 * 
 * <p>Example of a Service whose dependency filter is configured from ConfigAdmin:
 * 
 * <blockquote><pre>
 *  &#47;**
 *    * A Service whose service dependency filter/require attribute may be configured from ConfigAdmin
 *    *&#47;
 *  &#64;Service
 *  class X {
 *      private Dictionary m_config;
 *      
 *      &#64;ConfigurationDependency(pid="MyPid")
 *      void configure(Dictionary conf) {
 *           // Initialize our service from config ...
 *           
 *           // And store the config for later usage (from our init method)
 *           m_config = config;
 *      }
 *      
 *      &#64;ServiceDependency(name="dependency1") 
 *      void bindOtherService(OtherService other) {
 *         // the filter and required flag will be configured from our init method.
 *      }
 *
 *      // The returned Map will be used to configure our "dependency1" Dependency.
 *      &#64;Init
 *      Map init() {
 *          return new HashMap() {{
 *              put("dependency1.filter", m_config.get("filter"));
 *              put("dependency1.required", m_config.get("required"));
 *          }};
 *      } 
 *  }
 *  </pre></blockquote>
 *  
 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
 */
public class ServiceLifecycleHandler
{
    private final String m_init;
    private final String m_start;
    private final String m_stop;
    private final String m_destroy;
    private final MetaData m_srvMeta;
    private final List<MetaData> m_depsMeta;
    private final Bundle m_bundle;
    private final static Object SYNC = new Object();

    /**
     * Makes a new ServiceLifecycleHandler object. This objects allows to decorate the "init" service callback, in
     * order to see if "init" callback returns a dependency customization map.
     * 
     * @param srv The Service for the annotated class
     * @param srvBundle the Service bundle
     * @param dm The DependencyManager that was used to create the service
     * @param srvMeta The Service MetaData
     * @param depMeta The Dependencies MetaData
     */
    public ServiceLifecycleHandler(Component srv, Bundle srvBundle, DependencyManager dm,
                                   MetaData srvMeta, List<MetaData> depMeta)
    {
        m_srvMeta = srvMeta;
        m_init = srvMeta.getString(Params.init, null);
        m_start = srvMeta.getString(Params.start, null);
        m_stop = srvMeta.getString(Params.stop, null);
        m_destroy = srvMeta.getString(Params.destroy, null);
        m_bundle = srvBundle;
        m_depsMeta = depMeta;
    }

    /**
     * Handles an "init" lifecycle service callback. We just catch the "init" method, and callback 
     * the actual Service' init method, to see if a dependency customization map is returned.
     * We also check if a Lifecycle Controller is used. In this case, we add a hidden custom dependency,
     * allowing to take control of when the component is actually started/stopped.
     * We also handle an edge case described in FELIX-4050, where component state calculation 
     * may mess up if some dependencies are added using the API from the init method.
     * 
     * @param c The Annotated Component
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public void init(Component c)
        throws Exception
    {
        Object serviceInstance = c.getInstances()[0];
        DependencyManager dm = c.getDependencyManager();

        // Check if a lifecycle controller is defined for this service. If true, then 
        // We'll use the ToggleServiceDependency in order to manually activate/deactivate 
        // the component ...
        String starter = m_srvMeta.getString(Params.starter, null);
        String stopper = m_srvMeta.getString(Params.stopper, null);

        if (starter != null)
        {
            // We'll inject two runnables: one that will start or service, when invoked, and the other
            // that will stop our service, when invoked. We'll use a shared atomic boolean in order to
            // synchronize both runnables.
            Log.instance().debug("Setting up a lifecycle controller for service %s", serviceInstance);
            String componentName = serviceInstance.getClass().getName();
            // Create a toggle service, used to start/stop our service.
            ToggleServiceDependency toggle = new ToggleServiceDependency();
            AtomicBoolean startFlag = new AtomicBoolean(false);
            // Add the toggle dependency to the component.
            c.add(toggle);
            
            // Inject the runnable that will start our service, when invoked.
            setField(serviceInstance, starter, Runnable.class, new ComponentStarter(componentName, toggle, startFlag));
            if (stopper != null) {
                // Inject the runnable that will stop our service, when invoked.
                setField(serviceInstance, stopper, Runnable.class, new ComponentStopper(componentName, toggle, startFlag));
            }
        }

        // Before invoking an optional init method, we have to handle an edge case (FELIX-4050), where
        // init may add dependencies using the API and also return a map for configuring some
        // named dependencies. We have to add a hidden toggle dependency in the component, which we'll 
        // active *after* the init method is called, and possibly *after* named dependencies are configured.
        
        ToggleServiceDependency initToggle = null;
        if (m_init != null) 
        {
            initToggle = new ToggleServiceDependency();
            c.add(initToggle); 
        }
        
        // Invoke component and all composites init methods, and for each one, check if a dependency
        // customization map is returned by the method. This map will be used to configure 
        // some dependency filters (or required flag).

        Map<String, String> customization = new HashMap<String, String>();
        Object[] composites = c.getInstances();
        for (Object composite: composites)
        {
            Object o = invokeMethod(composite, m_init, dm, c);
            if (o != null && Map.class.isAssignableFrom(o.getClass()))
            {
                customization.putAll((Map) o);
            }
        }

        Log.instance().debug("ServiceLifecycleHandler.init: invoked init method from service %s " +
                             ", returned map: %s", serviceInstance, customization);
        
        // Apply name dependency filters possibly returned by the init() method.
        
        List<Dependency> nameDependencies = new ArrayList<>();
        for (MetaData dependency: m_depsMeta)
        {
            // Check if this dependency has a name, and if we find the name from the 
            // customization map, then apply filters and required flag from the map into it.
            // Also parse optional pid/propagate flags for named Configuration dependencies

            String name = dependency.getString(Params.name, null);
            if (name != null)
            {
                String filter = customization.get(name + ".filter");
                String required = customization.get(name + ".required");
                String pid = customization.get(name + ".pid");
                String propagate = customization.get(name + ".propagate");

                if (filter != null || required != null || pid != null || propagate != null)
                {
                    dependency = (MetaData) dependency.clone();
                    if (filter != null)
                    {
                        dependency.setString(Params.filter, filter);
                    }
                    if (required != null)
                    {
                        dependency.setString(Params.required, required);
                    }
                    if (pid != null)
                    {
                        dependency.setString(Params.pid, pid);
                    }
                    if (propagate != null)
                    {
                        dependency.setString(Params.propagate, propagate);
                    }
                }

                DependencyBuilder depBuilder = new DependencyBuilder(dependency);
                Log.instance().info("ServiceLifecycleHandler.init: adding dependency %s into service %s", dependency, m_srvMeta);
                nameDependencies.add(depBuilder.build(m_bundle, dm));
            }            
        }
        
        // Add all extra dependencies
        if (nameDependencies.size() > 0) 
        {
            Log.instance().info("ServiceLifecycleHandler.init: adding extra/named dependencies %s", nameDependencies);
            c.add(nameDependencies.toArray(new Dependency[nameDependencies.size()]));
        }    

        // init method fully handled, and all possible named dependencies have been configured. Now, activate the 
        // hidden toggle, and then remove it from the component, because we don't need it anymore.
        if (initToggle != null) 
        {
            c.remove(initToggle);
        } 
    }

    /**
     * Handles the Service's start lifecycle callback. We just invoke the service "start" service callback on 
     * the service instance, as well as on all eventual service composites.
     * We take care to check if a start callback returns a Map, which is meant to contain
     * some additional properties which must be appended to existing service properties.
     * Such extra properties takes precedence over existing service properties.
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public void start(Component service)
        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
    {
        // Check if some extra service properties are returned by start method.
        
        DependencyManager dm = service.getDependencyManager();
        Map<String, String> extraProperties = new HashMap<String, String>();
        Object[] composites = service.getInstances();
        for (Object composite: composites)
        {
            Object o = invokeMethod(composite, m_start, dm, service);
            if (o != null && Map.class.isAssignableFrom(o.getClass()))
            {
                extraProperties.putAll((Map) o);
            }
        }

        if (extraProperties.size() > 0)
        {
            // Store extra properties returned by start callbacks into existing service properties
            Dictionary existingProperties = service.getServiceProperties();
            if (existingProperties != null)
            {
                Hashtable props = new Hashtable();
                Enumeration e = existingProperties.keys();
                while (e.hasMoreElements())
                {
                    Object key = e.nextElement();
                    props.put(key, existingProperties.get(key));
                }
                props.putAll(extraProperties);
                service.setServiceProperties(props);
            }
            else
            {
                service.setServiceProperties(new Hashtable(extraProperties));
            }
        }        
    }

    /**
     * Handles the Service's stop lifecycle callback. We just invoke the service "stop" callback on 
     * the service instance, as well as on all eventual service composites.
     */
    public void stop(Component service)
        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
    {
        callbackComposites(service, m_stop);
    }

    /**
     * Handles the Service's destroy lifecycle callback. We just invoke the service "destroy" callback on 
     * the service instance, as well as on all eventual service composites.
     */
    public void destroy(Component service)
        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
    {
        callbackComposites(service, m_destroy);
    }

    /**
     * Invoke a callback on all Service compositions.
     */
    private void callbackComposites(Component service, String callback)
        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
    {
        Object[] composites = service.getInstances();
        for (Object composite: composites)
        {
            invokeMethod(composite, callback, service.getDependencyManager(), service);
        }
    }

    /**
     * Invoke a callback on an Object instance.
     */
    private Object invokeMethod(Object serviceInstance, String method, DependencyManager dm, Component c)
        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
    {
        if (method != null)
        {
            try
            {
                return InvocationUtil.invokeCallbackMethod(serviceInstance, method,
                                                           new Class[][] { { Component.class }, {} },
                                                           new Object[][] { { c }, {} }
                    );
            }

            catch (NoSuchMethodException e)
            {
                // ignore this
            }

            // Other exception will be thrown up to the ServiceImpl.invokeCallbackMethod(), which is 
            // currently invoking our method. So, no need to log something here, since the invokeCallbackMethod 
            // method is already logging any thrown exception.
        }
        return null;
    }

    /**
     * Sets a field of an object by reflexion.
     */
    private void setField(Object instance, String fieldName, Class<?> fieldClass, Object fieldValue)
    {
        Object serviceInstance = instance;
        Class<?> serviceClazz = serviceInstance.getClass();
        if (Proxy.isProxyClass(serviceClazz))
        {
            serviceInstance = Proxy.getInvocationHandler(serviceInstance);
            serviceClazz = serviceInstance.getClass();
        }
        while (serviceClazz != null)
        {
            Field[] fields = serviceClazz.getDeclaredFields();
            for (int j = 0; j < fields.length; j++)
            {
                Field field = fields[j];
                Class<?> type = field.getType();
                if (field.getName().equals(fieldName) && type.isAssignableFrom(fieldClass))
                {
                    try
                    {
                        field.setAccessible(true);
                        // synchronized makes sure the field is actually written to immediately
                        synchronized (SYNC)
                        {
                            field.set(serviceInstance, fieldValue);
                        }
                    }
                    catch (Throwable e)
                    {
                        throw new RuntimeException("Could not set field " + field, e);
                    }
                }
            }
            serviceClazz = serviceClazz.getSuperclass();
        }
    }
    
    private static class ComponentStarter implements Runnable {
        private final String m_componentName;
        private final ToggleServiceDependency m_toggle;
        private final AtomicBoolean m_startFlag;

        public ComponentStarter(String name, ToggleServiceDependency toggle, AtomicBoolean startFlag)
        {
            m_componentName = name;
            m_toggle = toggle;
            m_startFlag = startFlag;
        }

        @SuppressWarnings("synthetic-access")
        public void run()
        {
            if (m_startFlag.compareAndSet(false, true)) {
                Log.instance().debug("Lifecycle controller is activating the component %s",
                                     m_componentName);
                m_toggle.activate(true);
            }
        }
    }
    
    private static class ComponentStopper implements Runnable {
        private final Object m_componentName;
        private final ToggleServiceDependency m_toggle;
        private final AtomicBoolean m_startFlag;

        public ComponentStopper(String componentName, ToggleServiceDependency toggle, AtomicBoolean startFlag)
        {
            m_componentName = componentName;
            m_toggle = toggle;
            m_startFlag = startFlag;
        }

        @SuppressWarnings("synthetic-access")
        public void run()
        {
            if (m_startFlag.compareAndSet(true, false)) {
                Log.instance().debug("Lifecycle controller is deactivating the component %s",
                                    m_componentName);
                m_toggle.activate(false);
            }
        }
    }
}
