/*
 * 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.impl.dependencies;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;

import org.apache.felix.dm.ConfigurationDependency;
import org.apache.felix.dm.Dependency;
import org.apache.felix.dm.DependencyActivation;
import org.apache.felix.dm.DependencyService;
import org.apache.felix.dm.PropertyMetaData;
import org.apache.felix.dm.ServiceComponentDependency;
import org.apache.felix.dm.impl.InvocationUtil;
import org.apache.felix.dm.impl.Logger;
import org.apache.felix.dm.impl.metatype.MetaTypeProviderImpl;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
import org.osgi.service.log.LogService;

/**
 * Configuration dependency that can track the availability of a (valid) configuration.
 * To use it, specify a PID for the configuration. The dependency is always required,
 * because if it is not, it does not make sense to use the dependency manager. In that
 * scenario, simply register your service as a <code>ManagedService(Factory)</code> and
 * handle everything yourself. Also, only managed services are supported, not factories.
 * There are a couple of things you need to be aware of when implementing the
 * <code>updated(Dictionary)</code> method:
 * <ul>
 * <li>Make sure it throws a <code>ConfigurationException</code> when you get a
 * configuration that is invalid. In this case, the dependency will not change:
 * if it was not available, it will still not be. If it was available, it will
 * remain available and implicitly assume you keep working with your old
 * configuration.</li>
 * <li>This method will be called before all required dependencies are available.
 * Make sure you do not depend on these to parse your settings.</li>
 * </ul>
 * 
 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
 */
public class ConfigurationDependencyImpl extends DependencyBase implements ConfigurationDependency, ManagedService, ServiceComponentDependency, DependencyActivation {
	private BundleContext m_context;
	private String m_pid;
	private ServiceRegistration m_registration;
    protected List m_services = new ArrayList();
	private Dictionary m_settings;
    private String m_callback;
    private boolean m_isStarted;
	private final Set m_updateInvokedCache = new HashSet();
    private MetaTypeProviderImpl m_metaType;
    private boolean m_propagate;
    private Object m_propagateCallbackInstance;
    private String m_propagateCallbackMethod;
	
	public ConfigurationDependencyImpl(BundleContext context, Logger logger) {
	    super(logger);
		m_context = context;
	}
	
	public ConfigurationDependencyImpl(ConfigurationDependencyImpl prototype) {
	    super(prototype);
	    m_context = prototype.m_context;
	    m_pid = prototype.m_pid;
	    m_propagate = prototype.m_propagate;
	    m_callback = prototype.m_callback;
	}
	
	public Dependency createCopy() {
	    return new ConfigurationDependencyImpl(this);
	}
	
	public synchronized boolean isAvailable() {
		return m_settings != null;
	}

	/**
	 * Will always return <code>true</code> as optional configuration dependencies
	 * do not make sense. You might as well just implement <code>ManagedService</code>
	 * yourself in those cases.
	 */
	public boolean isRequired() {
		return true;
	}
	
	/**
	 * Returns <code>true</code> when configuration properties should be propagated
	 * as service properties.
	 */
	public boolean isPropagated() {
		return m_propagate;
	}
	
    public ConfigurationDependency setInstanceBound(boolean isInstanceBound) {
        setIsInstanceBound(isInstanceBound);
        return this;
    }

	
	public Dictionary getConfiguration() {
		return m_settings;
	}
	
	public void start(DependencyService service) {
	    boolean needsStarting = false;
	    synchronized (this) {
	        m_services.add(service);
	        if (!m_isStarted) {
	            m_isStarted = true;
                needsStarting = true;
	        }
	    }
	    if (needsStarting) {
	        Properties props = new Properties();
	        props.put(Constants.SERVICE_PID, m_pid);
	        ManagedService ms = this;
	        if (m_metaType != null) {
	            ms = m_metaType;
	        }
	        m_registration = m_context.registerService(ManagedService.class.getName(), ms, props);
	    }
	}

	public void stop(DependencyService service) {
        boolean needsStopping = false;
        synchronized (this) {
            if (m_services.size() == 1 && m_services.contains(service)) {
                m_isStarted = false;
                needsStopping = true;
            }
        }
        if (needsStopping) {
            m_registration.unregister();
            m_registration = null;
            m_services.remove(service);
        }
	}

    public ConfigurationDependency setCallback(String callback) {
		m_callback = callback;
		return this;
	}

	public void updated(Dictionary settings) throws ConfigurationException {
	    synchronized (m_updateInvokedCache) {
	        m_updateInvokedCache.clear();
	    }
	    Dictionary oldSettings = null; 
	    synchronized (this) {
	        oldSettings = m_settings;
	    }
	    
	    if (oldSettings == null && settings == null) {
	        // CM has started but our configuration is not still present in the CM database: ignore
	        return;
	    }

	    Object[] services = m_services.toArray();
        for (int i = 0; i < services.length; i++) {
            DependencyService ds = (DependencyService) services[i];
            // if non-null settings come in, we have to instantiate the service and
            // apply these settings
            ds.initService();
            Object service = ds.getService();

            if (service != null) {
                invokeUpdate(ds, service, settings);
            }
            else {
                m_logger.log(Logger.LOG_ERROR, "Service " + ds + " with configuration dependency " + this + " could not be instantiated.");
                return;
            }
        }

		synchronized (this) {
			m_settings = settings;
		}
		
        for (int i = 0; i < services.length; i++) {
            DependencyService ds = (DependencyService) services[i];
            // If these settings did not cause a configuration exception, we determine if they have 
            // caused the dependency state to change
            if ((oldSettings == null) && (settings != null)) {
                ds.dependencyAvailable(this);
            }
            if ((oldSettings != null) && (settings == null)) {
                ds.dependencyUnavailable(this);
            }
            if ((oldSettings != null) && (settings != null)) {
                ds.dependencyChanged(this);
            }
        }
	}

    public void invokeUpdate(DependencyService ds, Object service, Dictionary settings) throws ConfigurationException {
        boolean wasAdded;
        synchronized (m_updateInvokedCache) {
            wasAdded = m_updateInvokedCache.add(ds);
        }
        if (wasAdded) {
            String callback = (m_callback == null) ? "updated" : m_callback;
            try {
                // if exception is thrown here, what does that mean for the
                // state of this dependency? how smart do we want to be??
                // it's okay like this, if the new settings contain errors, we
                // remain in the state we were, assuming that any error causes
                // the "old" configuration to stay in effect.
                // CM will log any thrown exceptions.
                InvocationUtil.invokeMethod(service, service.getClass(), callback, new Class[][] {{ Dictionary.class }}, new Object[][] {{ settings }}, false);
            } 
            catch (InvocationTargetException e) {
                // The component has thrown an exception during it's callback invocation.
                if (e.getTargetException() instanceof ConfigurationException) {
                    // the callback threw an OSGi ConfigurationException: just re-throw it.
                    throw (ConfigurationException) e.getTargetException();
                }
                else {
                    // wrap the callback exception into a ConfigurationException.
                    throw new ConfigurationException(null, "Service " + ds + " with " + this.toString() + " could not be updated", e.getTargetException());
                }
            }
            catch (NoSuchMethodException e) {
                // if the method does not exist, ignore it
            }
            catch (Throwable t) {
                // wrap any other exception as a ConfigurationException.
                throw new ConfigurationException(null, "Service " + ds + " with " + this.toString() + " could not be updated", t);
            }
        }
    }

	/**
	 * Sets the <code>service.pid</code> of the configuration you
	 * are depending on.
	 */
	public ConfigurationDependency setPid(String pid) {
		ensureNotActive();
		m_pid = pid;
		return this;
	}

	/**
	 * Sets propagation of the configuration properties to the service
	 * properties. Any additional service properties specified directly
	 * are merged with these.
	 */
	public ConfigurationDependency setPropagate(boolean propagate) {
		ensureNotActive();
		m_propagate = propagate;
		return this;
	}
	
	private void ensureNotActive() {
	  	if (m_services != null && m_services.size() > 0) {
	  	  throw new IllegalStateException("Cannot modify state while active.");
	  	}
    }
    
    public String toString() {
    	return "ConfigurationDependency[" + m_pid + "]";
    }

    public String getName() {
        return m_pid;
    }

    public int getState() {
        return (isAvailable() ? 1 : 0) + (isRequired() ? 2 : 0);
    }

    public String getType() {
        return "configuration";
    }

    public Object getAutoConfigInstance() {
        return getConfiguration();
    }

    public String getAutoConfigName() {
        // TODO Auto-generated method stub
        return null;
    }

    public Class getAutoConfigType() {
        return Dictionary.class;
    }

    public void invokeAdded(DependencyService service) {
        try {
            invokeUpdate(service, service.getService(), getConfiguration());
        }
        catch (ConfigurationException e) {
            // if this happens, it's definitely an inconsistency, since we
            // asked the instance the same question before (if this is a
            // valid configuration) and then it was
            e.printStackTrace();
        }
    }

    public void invokeRemoved(DependencyService service) {
        // TODO Auto-generated method stub
    }

    public boolean isAutoConfig() {
        // TODO Auto-generated method stub
        return false;
    }

    public ConfigurationDependency setPropagate(Object instance, String method) {
        setPropagate(instance != null && method != null);
        m_propagateCallbackInstance = instance;
        m_propagateCallbackMethod = method;
        return this;
    }
    
    public Dictionary getProperties() {
        Dictionary config = getConfiguration();
        if (config != null) {
            if (m_propagateCallbackInstance != null && m_propagateCallbackMethod != null) {
                try {
                    return (Dictionary) InvocationUtil.invokeCallbackMethod(m_propagateCallbackInstance, m_propagateCallbackMethod, new Class[][] {{ Dictionary.class }, {}}, new Object[][] {{ config }, {}});
                }
                catch (InvocationTargetException e) {
                    m_logger.log(LogService.LOG_WARNING, "Exception while invoking callback method", e.getCause());
                }
                catch (Exception e) {
                    m_logger.log(LogService.LOG_WARNING, "Exception while trying to invoke callback method", e);
                }
                throw new IllegalStateException("Could not invoke callback");
            }
            else {
                return config;
            }
        }
        else {
            throw new IllegalStateException("cannot find configuration");
        }
    }
    
    public BundleContext getBundleContext() {
        return m_context;
    }
    
    public Logger getLogger() {
        return m_logger;
    }
    
    public ConfigurationDependency add(PropertyMetaData properties)
    {
        createMetaTypeImpl();
        m_metaType.add(properties);
       return this;
    }

    public ConfigurationDependency setDescription(String description)
    {
        createMetaTypeImpl();
        m_metaType.setDescription(description);
       return this;
    }

    public ConfigurationDependency setHeading(String heading)
    {
        createMetaTypeImpl();
        m_metaType.setName(heading);
       return this;
    }
    
    public ConfigurationDependency setLocalization(String path)
    {
        createMetaTypeImpl();
        m_metaType.setLocalization(path);
        return this;
    }
    
    private synchronized void createMetaTypeImpl() {
        if (m_metaType == null) {
            m_metaType = new MetaTypeProviderImpl(getName(), getBundleContext(), getLogger(), this, null);
        }
    }
}
