/*
 * 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;

import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;

import org.apache.felix.dm.Component;
import org.apache.felix.dm.ComponentDependencyDeclaration;
import org.apache.felix.dm.ResourceDependency;
import org.apache.felix.dm.ResourceHandler;
import org.apache.felix.dm.context.AbstractDependency;
import org.apache.felix.dm.context.DependencyContext;
import org.apache.felix.dm.context.Event;
import org.apache.felix.dm.context.EventType;
import org.osgi.framework.ServiceRegistration;

/**
 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
 */
public class ResourceDependencyImpl extends AbstractDependency<ResourceDependency> implements ResourceDependency, ResourceHandler, ComponentDependencyDeclaration {
    private volatile ServiceRegistration<?> m_registration;
    private volatile String m_resourceFilter;
    private volatile URL m_trackedResource;

    public ResourceDependencyImpl() {
    }
    
    public ResourceDependencyImpl(ResourceDependencyImpl prototype) {
        super(prototype);
        m_resourceFilter = prototype.m_resourceFilter;
        m_trackedResource = prototype.m_trackedResource;
    }
    
    @Override
    public DependencyContext createCopy() {
        return new ResourceDependencyImpl(this);
    }
    
    @Override
    public void start() {
        Dictionary<String, Object> props = null;
        if (m_trackedResource != null) {
            props = new Hashtable<>();
            props.put(ResourceHandler.URL, m_trackedResource);
        } else {
            if (m_resourceFilter != null) {
                props = new Hashtable<>();
                props.put(ResourceHandler.FILTER, m_resourceFilter);
            }
        }
        m_registration = m_component.getBundleContext().registerService(ResourceHandler.class.getName(), this, props);
        super.start();
    }

    @Override
    public void stop() {
        m_registration.unregister();
        m_registration = null;
        super.stop();
    }

    public void added(URL resource) {
        if (m_trackedResource == null || m_trackedResource.equals(resource)) {
            getComponentContext().handleEvent(this, EventType.ADDED, new ResourceEventImpl(resource, null));
        }
    }
    
    public void added(URL resource, Dictionary<?, ?> resourceProperties) {
        if (m_trackedResource == null || m_trackedResource.equals(resource)) {
            getComponentContext().handleEvent(this, EventType.ADDED, new ResourceEventImpl(resource, resourceProperties));
        }
    }
        
    public void changed(URL resource) {
        if (m_trackedResource == null || m_trackedResource.equals(resource)) {
            m_component.handleEvent(this, EventType.CHANGED, new ResourceEventImpl(resource, null));
        }
    }
    
    public void changed(URL resource, Dictionary<?, ?> resourceProperties) {
        if (m_trackedResource == null || m_trackedResource.equals(resource)) {
            m_component.handleEvent(this, EventType.CHANGED, new ResourceEventImpl(resource, resourceProperties));
        }
    }

    public void removed(URL resource) {
        if (m_trackedResource == null || m_trackedResource.equals(resource)) {
            m_component.handleEvent(this, EventType.REMOVED, new ResourceEventImpl(resource, null));
        }
    }
    
    public void removed(URL resource, Dictionary<?, ?> resourceProperties) {
        if (m_trackedResource == null || m_trackedResource.equals(resource)) {
            m_component.handleEvent(this, EventType.REMOVED, new ResourceEventImpl(resource, resourceProperties));
        }
    }
    
    @Override
    public void invokeCallback(EventType type, Event ... e) {
        switch (type) {
        case ADDED:
            if (m_add != null) {
                invoke(m_add, e[0]);
            }
            break;
        case CHANGED:
            if (m_change != null) {
                invoke (m_change, e[0]);
            }
            break;
        case REMOVED:
            if (m_remove != null) {
                invoke (m_remove, e[0]);
            }
            break;
        default:
            break;
        }
    }
    
    private void invoke(String method, Event e) {
        ResourceEventImpl re = (ResourceEventImpl) e;
        URL serviceInstance = re.getResource();
        Dictionary<?,?> resourceProperties = re.getProperties();
       
        m_component.invokeCallbackMethod(getInstances(), method,
            new Class[][] {
                    { Component.class, URL.class, Dictionary.class }, 
                    { Component.class, URL.class },
                    { Component.class },  
                    { URL.class, Dictionary.class }, 
                    { URL.class },
                    { Object.class }, 
                    {}},
            new Object[][] {
                    { m_component, serviceInstance, resourceProperties }, 
                    { m_component, serviceInstance }, 
                    { m_component }, 
                    { serviceInstance, resourceProperties },
                    { serviceInstance },
                    { serviceInstance }, 
                    {}}
        );

    }  
                    
    public ResourceDependency setResource(URL resource) {
        m_trackedResource = resource;
        return this;
    }
    
    public ResourceDependency setFilter(String resourceFilter) {
        ensureNotActive();
        m_resourceFilter = resourceFilter;
        return this;
    }
    
    public ResourceDependency setFilter(String resourceFilter, String resourcePropertiesFilter) {
        ensureNotActive();
        m_resourceFilter = resourceFilter;
        return this;
    }
    
    @Override
    public Class<?> getAutoConfigType() {
        return URL.class;
    }
        
    @SuppressWarnings("unchecked")
    public Dictionary<String, Object> getProperties() {
        ResourceEventImpl re = (ResourceEventImpl) m_component.getDependencyEvent(this);
        if (re != null) {
            URL resource = re.getResource();
            Dictionary<String, Object> resourceProperties = re.getProperties();
            if (m_propagateCallbackInstance != null && m_propagateCallbackMethod != null) {
                try {
                    CallbackTypeDef callbackInfo = new CallbackTypeDef(URL.class, resource);
                    return (Dictionary<String, Object>) InvocationUtil.invokeCallbackMethod(m_propagateCallbackInstance, m_propagateCallbackMethod, callbackInfo.m_sigs, callbackInfo.m_args);
                }
                catch (InvocationTargetException e) {
                    m_component.getLogger().warn("Exception while invoking callback method", e.getCause());
                }
                catch (Throwable e) {
                    m_component.getLogger().warn("Exception while trying to invoke callback method", e);
                }
                throw new IllegalStateException("Could not invoke callback");
            }
            else {
                Hashtable<String, Object> props = new Hashtable<>();
                props.put(ResourceHandler.HOST, resource.getHost());
                props.put(ResourceHandler.PATH, resource.getPath());
                props.put(ResourceHandler.PROTOCOL, resource.getProtocol());
                props.put(ResourceHandler.PORT, Integer.toString(resource.getPort()));
                // add the custom resource properties
                if (resourceProperties != null) {
                    Enumeration<String> properyKeysEnum = resourceProperties.keys(); 
                    while (properyKeysEnum.hasMoreElements()) {
                        String key = properyKeysEnum.nextElement();
                        if (!key.equals(ResourceHandler.HOST) &&
                                !key.equals(ResourceHandler.PATH) &&
                                !key.equals(ResourceHandler.PROTOCOL) &&
                                !key.equals(ResourceHandler.PORT)) {
                            props.put(key, resourceProperties.get(key).toString());
                        } else {
                            m_component.getLogger().warn(
                                "Custom resource property is overlapping with the default resource property for key: %s",
                                key);
                        }
                    }
                }
                return props;
            }
        }
        else {
            throw new IllegalStateException("cannot find resource");
        }
    }
    
    @Override
    public String getName() {
        StringBuilder sb = new StringBuilder();
        if (m_trackedResource != null) {
            sb.append(m_trackedResource.toString());
        }
        if (m_resourceFilter != null) {
            sb.append(m_resourceFilter);
        }
        return sb.toString();
    }
    
    @Override
    public String getSimpleName() {
        return m_trackedResource != null ? m_trackedResource.toString() : null;
    }

    @Override
    public String getFilter() {
        return m_resourceFilter;
    }

    @Override
    public String getType() {
        return "resource";
    }
}
