/*
 * 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.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.apache.felix.dm.dependencies.ResourceDependency;
import org.apache.felix.dm.impl.Logger;
import org.apache.felix.dm.resources.Resource;
import org.apache.felix.dm.resources.ResourceHandler;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;

public class ResourceDependencyImpl implements ResourceDependency, ResourceHandler, DependencyActivation {
	private volatile BundleContext m_context;
	private volatile ServiceRegistration m_registration;
	private long m_resourceCounter;

    private Object m_callbackInstance;
    private String m_callbackAdded;
    private String m_callbackChanged;
    private String m_callbackRemoved;
    private boolean m_autoConfig;
    private final Logger m_logger;
    private String m_autoConfigInstance;
//    private DependencyService m_service;
    protected List m_services = new ArrayList();
	private boolean m_isRequired;
	private String m_resourceFilter;
	private Resource m_resource;
	private Resource m_trackedResource;
    private boolean m_isStarted;

	
    public ResourceDependencyImpl(BundleContext context, Logger logger) {
    	m_context = context;
    	m_logger = logger;
    	m_autoConfig = true;
    }
    
	public synchronized boolean isAvailable() {
		return m_resourceCounter > 0;
	}

	public boolean isRequired() {
		return m_isRequired;
	}
	
	public boolean isInstanceBound() {
		return false; // TODO for now we are never bound to the service implementation instance
	}

	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.setProperty(Resource.FILTER, m_resourceFilter);
	        m_registration = m_context.registerService(ResourceHandler.class.getName(), this, 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;
                m_services.remove(service);
            }
	    }
	    if (needsStopping) {
	        m_registration.unregister();
	        m_registration = null;
	    }
	}

	public void added(Resource resource) {
		long counter;
		Object[] services;
		synchronized (this) {
			m_resourceCounter++;
			counter = m_resourceCounter;
			m_resource = resource; // TODO this really sucks as a way to track a single resource
			services = m_services.toArray();
		}
        for (int i = 0; i < services.length; i++) {
            DependencyService ds = (DependencyService) services[i];
            if (counter == 1) {
                ds.dependencyAvailable(this);
                if (!isRequired()) {
                    invokeAdded(ds, resource);
                }
            }
            else {
                ds.dependencyChanged(this);
                invokeAdded(ds, resource);
            }
        }
	}

	public void changed(Resource resource) {
        Object[] services;
        synchronized (this) {
            services = m_services.toArray();
        }
        for (int i = 0; i < services.length; i++) {
            DependencyService ds = (DependencyService) services[i];
            invokeChanged(ds, resource);
        }
	}

	public void removed(Resource resource) {
		long counter;
		Object[] services;
		synchronized (this) {
			m_resourceCounter--;
			counter = m_resourceCounter;
			services = m_services.toArray();
		}
        for (int i = 0; i < services.length; i++) {
            DependencyService ds = (DependencyService) services[i];
            if (counter == 0) {
                ds.dependencyUnavailable(this);
                if (!isRequired()) {
                    invokeRemoved(ds, resource);
                }
            }
            else {
                ds.dependencyChanged(this);
                invokeRemoved(ds, resource);
            }
        }
	}
	
    public void invokeAdded(DependencyService ds, Resource serviceInstance) {
        Object[] callbackInstances = getCallbackInstances(ds);
        if ((callbackInstances != null) && (m_callbackAdded != null)) {
            invokeCallbackMethod(callbackInstances, m_callbackAdded, serviceInstance);
        }
    }

    public void invokeChanged(DependencyService ds, Resource serviceInstance) {
        Object[] callbackInstances = getCallbackInstances(ds);
        if ((callbackInstances != null) && (m_callbackChanged != null)) {
            invokeCallbackMethod(callbackInstances, m_callbackChanged, serviceInstance);
        }
    }

    public void invokeRemoved(DependencyService ds, Resource serviceInstance) {
        Object[] callbackInstances = getCallbackInstances(ds);
        if ((callbackInstances != null) && (m_callbackRemoved != null)) {
            invokeCallbackMethod(callbackInstances, m_callbackRemoved, serviceInstance);
        }
    }

    /**
     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
     * dependency is added or removed. When you specify callbacks, the auto configuration 
     * feature is automatically turned off, because we're assuming you don't need it in this 
     * case.
     * 
     * @param added the method to call when a service was added
     * @param removed the method to call when a service was removed
     * @return this service dependency
     */
    public synchronized ResourceDependency setCallbacks(String added, String removed) {
        return setCallbacks(null, added, null, removed);
    }

    /**
     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
     * dependency is added, changed or removed. When you specify callbacks, the auto 
     * configuration feature is automatically turned off, because we're assuming you don't 
     * need it in this case.
     * 
     * @param added the method to call when a service was added
     * @param changed the method to call when a service was changed
     * @param removed the method to call when a service was removed
     * @return this service dependency
     */
    public synchronized ResourceDependency setCallbacks(String added, String changed, String removed) {
        return setCallbacks(null, added, changed, removed);
    }

    /**
     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
     * dependency is added or removed. They are called on the instance you provide. When you
     * specify callbacks, the auto configuration feature is automatically turned off, because
     * we're assuming you don't need it in this case.
     * 
     * @param instance the instance to call the callbacks on
     * @param added the method to call when a service was added
     * @param removed the method to call when a service was removed
     * @return this service dependency
     */
    public synchronized ResourceDependency setCallbacks(Object instance, String added, String removed) {
        return setCallbacks(instance, added, null, removed);
    }
    
    /**
     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
     * dependency is added, changed or removed. They are called on the instance you provide. When you
     * specify callbacks, the auto configuration feature is automatically turned off, because
     * we're assuming you don't need it in this case.
     * 
     * @param instance the instance to call the callbacks on
     * @param added the method to call when a service was added
     * @param changed the method to call when a service was changed
     * @param removed the method to call when a service was removed
     * @return this service dependency
     */
    public synchronized ResourceDependency setCallbacks(Object instance, String added, String changed, String removed) {
        ensureNotActive();
        // if at least one valid callback is specified, we turn off auto configuration
        if (added != null || removed != null || changed != null) {
            setAutoConfig(false);
        }
        m_callbackInstance = instance;
        m_callbackAdded = added;
        m_callbackChanged = changed;
        m_callbackRemoved = removed;
        return this;
    }
    
    private void ensureNotActive() {
        if (m_registration != null) {
            throw new IllegalStateException("Cannot modify state while active.");
        }
    }
    
    /**
     * Sets auto configuration for this service. Auto configuration allows the
     * dependency to fill in any attributes in the service implementation that
     * are of the same type as this dependency. Default is on.
     * 
     * @param autoConfig the value of auto config
     * @return this service dependency
     */
    public synchronized ResourceDependency setAutoConfig(boolean autoConfig) {
        ensureNotActive();
        m_autoConfig = autoConfig;
        return this;
    }
    
    /**
     * Sets auto configuration for this service. Auto configuration allows the
     * dependency to fill in the attribute in the service implementation that
     * has the same type and instance name.
     * 
     * @param instanceName the name of attribute to auto config
     * @return this service dependency
     */
    public synchronized ResourceDependency setAutoConfig(String instanceName) {
        ensureNotActive();
        m_autoConfig = (instanceName != null);
        m_autoConfigInstance = instanceName;
        return this;
    }
    
    private void invokeCallbackMethod(Object[] instances, String methodName, Object service) {
        for (int i = 0; i < instances.length; i++) {
            try {
                invokeCallbackMethod(instances[i], methodName, service);
            }
            catch (NoSuchMethodException e) {
                m_logger.log(Logger.LOG_DEBUG, "Method '" + methodName + "' does not exist on " + instances[i] + ". Callback skipped.");
            }
        }
    }

    private void invokeCallbackMethod(Object instance, String methodName, Object service) throws NoSuchMethodException {
        Class currentClazz = instance.getClass();
        boolean done = false;
        while (!done && currentClazz != null) {
            done = invokeMethod(instance, currentClazz, methodName,
                new Class[][] {{Resource.class}, {Object.class}, {}},
                new Object[][] {{service}, {service}, {}},
                false);
            if (!done) {
                currentClazz = currentClazz.getSuperclass();
            }
        }
        if (!done && currentClazz == null) {
            throw new NoSuchMethodException(methodName);
        }
    }
    
    private boolean invokeMethod(Object object, Class clazz, String name, Class[][] signatures, Object[][] parameters, boolean isSuper) {
        Method m = null;
        for (int i = 0; i < signatures.length; i++) {
            Class[] signature = signatures[i];
            try {
                m = clazz.getDeclaredMethod(name, signature);
                if (!(isSuper && Modifier.isPrivate(m.getModifiers()))) {
                    m.setAccessible(true);
                    try {
                        m.invoke(object, parameters[i]);
                    }
                    catch (InvocationTargetException e) {
                        m_logger.log(Logger.LOG_ERROR, "Exception while invoking method " + m + ".", e);
                    }
                    // we did find and invoke the method, so we return true
                    return true;
                }
            }
            catch (NoSuchMethodException e) {
                // ignore this and keep looking
            }
            catch (Exception e) {
                // could not even try to invoke the method
                m_logger.log(Logger.LOG_ERROR, "Exception while trying to invoke method " + m + ".", e);
            }
        }
        return false;
    }
    
    private synchronized Object[] getCallbackInstances(DependencyService ds) {
        if (m_callbackInstance == null) {
            return ds.getCompositionInstances();
        }
        else {
            return new Object[] { m_callbackInstance };
        }
    }

	public ResourceDependency setResource(Resource resource) {
		m_trackedResource = resource;
		return this;
	}
	
    public synchronized ResourceDependency setRequired(boolean required) {
        ensureNotActive();
        m_isRequired = required;
        return this;
    }

	public ResourceDependency setFilter(String resourceFilter) {
		m_resourceFilter = resourceFilter;
		return this;
	}
    public synchronized boolean isAutoConfig() {
        return m_autoConfig;
    }

    public Resource getResource() {
    	System.out.println("Fetching resource");
    	return m_resource;
    }
}
