/*
 * 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.sling.testing.mock.osgi;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.Comparator;
import java.util.Dictionary;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentSkipListSet;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.felix.framework.FilterImpl;
import org.apache.sling.testing.mock.osgi.OsgiMetadataUtil.DynamicReference;
import org.apache.sling.testing.mock.osgi.OsgiMetadataUtil.Reference;
import org.apache.sling.testing.mock.osgi.OsgiServiceUtil.ReferenceInfo;
import org.apache.sling.testing.mock.osgi.OsgiServiceUtil.ServiceInfo;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkListener;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceObjects;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.component.ComponentConstants;

import com.google.common.collect.ImmutableList;
import com.google.common.io.Files;

/**
 * Mock {@link BundleContext} implementation.
 */
class MockBundleContext implements BundleContext {

    private final MockBundle bundle;
    private final SortedSet<MockServiceRegistration> registeredServices = new ConcurrentSkipListSet<MockServiceRegistration>();
    private final Map<ServiceListener, Filter> serviceListeners = new ConcurrentHashMap<ServiceListener, Filter>();
    private final Queue<BundleListener> bundleListeners = new ConcurrentLinkedQueue<BundleListener>();
    private final ConfigurationAdmin configAdmin = new MockConfigurationAdmin();
    private File dataFileBaseDir;
    
    private final Bundle systemBundle;

    public MockBundleContext() {
        this.systemBundle = new MockBundle(this, Constants.SYSTEM_BUNDLE_ID);
        this.bundle = new MockBundle(this);
        
        // register configuration admin by default
        registerService(ConfigurationAdmin.class.getName(), configAdmin, null);
    }

    @Override
    public Bundle getBundle() {
        return this.bundle;
    }

    @Override
    public Filter createFilter(final String s) throws InvalidSyntaxException {
        if (s == null) {
            return new MatchAllFilter();
        }
        else {
            return new FilterImpl(s);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public ServiceRegistration registerService(final String clazz, final Object service, final Dictionary properties) {
        String[] clazzes;
        if (StringUtils.isBlank(clazz)) {
            clazzes = new String[0];
        } else {
            clazzes = new String[] { clazz };
        }
        return registerService(clazzes, service, properties);
    }

    @SuppressWarnings("unchecked")
    @Override
    public <S> ServiceRegistration<S> registerService(Class<S> clazz, S service, Dictionary<String, ?> properties) {
        return registerService(clazz.getName(), service, properties);
    }

    @SuppressWarnings("unchecked")
    @Override
    public ServiceRegistration registerService(final String[] clazzes, final Object service, final Dictionary properties) {
        Dictionary<String, Object> mergedPropertes = MapMergeUtil.propertiesMergeWithOsgiMetadata(service, configAdmin, properties);
        MockServiceRegistration registration = new MockServiceRegistration(this.bundle, clazzes, service, mergedPropertes, this);
        this.registeredServices.add(registration);
        handleRefsUpdateOnRegister(registration);
        notifyServiceListeners(ServiceEvent.REGISTERED, registration.getReference());
        return registration;
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public <S> ServiceRegistration<S> registerService(Class<S> clazz, ServiceFactory<S> factory, Dictionary<String, ?> properties) {
        return registerService(clazz.getName(), factory, properties);
    }
    
    /**
     * Check for already registered services that may be affected by the service registration - either
     * adding by additional optional references, or creating a conflict in the dependencies.
     * @param registration
     */
    private void handleRefsUpdateOnRegister(MockServiceRegistration registration) {
        
        // handle DYNAMIC references to this registration
        List<ReferenceInfo> affectedDynamicReferences = OsgiServiceUtil.getMatchingDynamicReferences(registeredServices, registration);
        for (ReferenceInfo referenceInfo : affectedDynamicReferences) {
            Reference reference = referenceInfo.getReference();
            // Look for a target override
            Object o = referenceInfo.getServiceRegistration().getProperties().get(reference.getName() + ComponentConstants.REFERENCE_TARGET_SUFFIX);
            if (o != null && o instanceof String) {
                reference = new DynamicReference(reference,(String)o);
            }
            if (reference.matchesTargetFilter(registration.getReference())) {
                switch (reference.getCardinality()) {
                case MANDATORY_UNARY:
                    // nothing to do - reference is already set
                    break;
                case MANDATORY_MULTIPLE:
                case OPTIONAL_MULTIPLE:
                case OPTIONAL_UNARY:
                    OsgiServiceUtil.invokeBindMethod(reference, referenceInfo.getServiceRegistration().getService(),
                            new ServiceInfo(registration));
                    break;
                default:
                    throw new RuntimeException("Unepxected cardinality: " + reference.getCardinality());
                }
            }
        }

        // handle STATIC+GREEDY references to this registration
        List<ReferenceInfo> affectedStaticGreedyReferences = OsgiServiceUtil.getMatchingStaticGreedyReferences(registeredServices, registration);
        for (ReferenceInfo referenceInfo : affectedStaticGreedyReferences) {
            Reference reference = referenceInfo.getReference();
            switch (reference.getCardinality()) {
            case MANDATORY_UNARY:
                // nothing to do - reference is already set
                break;
            case MANDATORY_MULTIPLE:
            case OPTIONAL_MULTIPLE:
            case OPTIONAL_UNARY:
                restartService(referenceInfo.getServiceRegistration());
                break;
            default:
                throw new RuntimeException("Unepxected cardinality: " + reference.getCardinality());
            }
        }
    }
    
    void unregisterService(MockServiceRegistration registration) {
        this.registeredServices.remove(registration);
        handleRefsUpdateOnUnregister(registration);
        notifyServiceListeners(ServiceEvent.UNREGISTERING, registration.getReference());
    }
    
    @SuppressWarnings({ "unchecked", "null" })
    void restartService(MockServiceRegistration registration) {
        // get current service properties
        Class<?> serviceClass = registration.getService().getClass();
        Map<String,Object> properties = MapUtil.toMap(registration.getProperties());
        
        // deactivate & unregister service
        MockOsgi.deactivate(registration.getService(), this);
        unregisterService(registration);
        
        // newly create and register service
        Object newService;
        try {
            newService = serviceClass.newInstance();
        }
        catch (InstantiationException e) {
            throw new RuntimeException("Unable to instantiate service: " + serviceClass);
        }
        catch (IllegalAccessException e) {
            throw new RuntimeException("Unable to access service class: " + serviceClass);
        }
        MockOsgi.injectServices(newService, this);
        MockOsgi.activate(newService, this, properties);
        registerService(serviceClass.getName(), newService, MapUtil.toDictionary(properties));
    }

    /**
     * Check for already registered services that may be affected by the service unregistration - either
     * adding by removing optional references, or creating a conflict in the dependencies.
     * @param registration
     */
    private void handleRefsUpdateOnUnregister(MockServiceRegistration registration) {

        // handle DYNAMIC references to this registration
        List<ReferenceInfo> affectedDynamicReferences = OsgiServiceUtil.getMatchingDynamicReferences(registeredServices, registration);
        for (ReferenceInfo referenceInfo : affectedDynamicReferences) {
            Reference reference = referenceInfo.getReference();
            if (reference.matchesTargetFilter(registration.getReference())) {
                switch (reference.getCardinality()) {
                case MANDATORY_UNARY:
                case MANDATORY_MULTIPLE:
                case OPTIONAL_MULTIPLE:
                case OPTIONAL_UNARY:
                    // it is currently not checked if for a MANDATORY_UNARY or MANDATORY_MULTIPLE reference the last reference is removed
                    OsgiServiceUtil.invokeUnbindMethod(reference, referenceInfo.getServiceRegistration().getService(),
                            new ServiceInfo(registration));
                    break;
                default:
                    throw new RuntimeException("Unepxected cardinality: " + reference.getCardinality());
                }
            }
        }

        // handle STATIC+GREEDY references to this registration
        List<ReferenceInfo> affectedStaticGreedyReferences = OsgiServiceUtil.getMatchingStaticGreedyReferences(registeredServices, registration);
        for (ReferenceInfo referenceInfo : affectedStaticGreedyReferences) {
            Reference reference = referenceInfo.getReference();
            switch (reference.getCardinality()) {
            case MANDATORY_UNARY:
            case MANDATORY_MULTIPLE:
            case OPTIONAL_MULTIPLE:
            case OPTIONAL_UNARY:
                restartService(referenceInfo.getServiceRegistration());
                break;
            default:
                throw new RuntimeException("Unepxected cardinality: " + reference.getCardinality());
            }
        }
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public ServiceReference getServiceReference(final String clazz) {
        try {
            ServiceReference[] serviceRefs = getServiceReferences(clazz, null);
            if (serviceRefs != null && serviceRefs.length > 0) {
                return serviceRefs[0];
            }
        }
        catch (InvalidSyntaxException ex) {
            // should not happen
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    @Override
    public <S> ServiceReference<S> getServiceReference(Class<S> clazz) {
        return getServiceReference(clazz.getName());
    }

    @SuppressWarnings("unchecked")
    @Override
    public ServiceReference[] getServiceReferences(final String clazz, final String filter) throws InvalidSyntaxException {
        Set<ServiceReference> result = new TreeSet<ServiceReference>(new Comparator<ServiceReference>() {
            @Override
            public int compare(ServiceReference o1, ServiceReference o2) {
                // reverse sort order to get highest ranking first
                return o2.compareTo(o1);
            }
        });
        for (MockServiceRegistration serviceRegistration : this.registeredServices) {
            if (serviceRegistration.matches(clazz, filter)) {
                result.add(serviceRegistration.getReference());
            }
        }
        if (result.isEmpty()) {
            return null;
        } else {
            return result.toArray(new ServiceReference[result.size()]);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public <S> Collection<ServiceReference<S>> getServiceReferences(Class<S> clazz, String filter) throws InvalidSyntaxException {
        ServiceReference<S>[] result = getServiceReferences(clazz.getName(), filter);
        if (result == null) {
            return ImmutableList.<ServiceReference<S>>of();
        }
        else {
            return ImmutableList.<ServiceReference<S>>copyOf(result);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public ServiceReference[] getAllServiceReferences(final String clazz, final String filter) throws InvalidSyntaxException {
        // for now just do the same as getServiceReferences
        return getServiceReferences(clazz, filter);
    }

    @Override
    public <S> S getService(final ServiceReference<S> serviceReference) {
        return ((MockServiceReference<S>)serviceReference).getService();
    }

    @Override
    public boolean ungetService(final ServiceReference serviceReference) {
        // do nothing for now
        return false;
    }

    @Override
    public void addServiceListener(final ServiceListener serviceListener) {
        try {
            addServiceListener(serviceListener, null);
        }
        catch (InvalidSyntaxException ex) {
            throw new RuntimeException(ex);
        }
    }

    @Override
    public void addServiceListener(final ServiceListener serviceListener, final String filter) throws InvalidSyntaxException {
        serviceListeners.put(serviceListener, createFilter(filter));
    }

    @Override
    public void removeServiceListener(final ServiceListener serviceListener) {
        serviceListeners.remove(serviceListener);
    }

    private void notifyServiceListeners(int eventType, ServiceReference serviceReference) {
        final ServiceEvent event = new ServiceEvent(eventType, serviceReference);
        for ( Map.Entry<ServiceListener, Filter> entry : serviceListeners.entrySet()) {
            if ( entry.getValue() == null || entry.getValue().match(serviceReference)) {
                entry.getKey().serviceChanged(event);
            }
        }
    }

    @Override
    public void addBundleListener(final BundleListener bundleListener) {
        if (!bundleListeners.contains(bundleListener)) {
            bundleListeners.add(bundleListener);
        }
    }

    @Override
    public void removeBundleListener(final BundleListener bundleListener) {
        bundleListeners.remove(bundleListener);
    }

    void sendBundleEvent(BundleEvent bundleEvent) {
        for (BundleListener bundleListener : bundleListeners) {
            bundleListener.bundleChanged(bundleEvent);
        }
    }

    @Override
    public void addFrameworkListener(final FrameworkListener frameworkListener) {
        // accept method, but ignore it
    }

    @Override
    public void removeFrameworkListener(final FrameworkListener frameworkListener) {
        // accept method, but ignore it
    }

    @SuppressWarnings({ "unchecked", "null" })
    <S> S locateService(final String name, final ServiceReference<S> reference) {
        for (MockServiceRegistration<?> serviceRegistration : this.registeredServices) {
            if (serviceRegistration.getReference() == reference) {
                return (S)serviceRegistration.getService();
            }
        }
        return null;
    }

    @Override
    public Bundle[] getBundles() {
        return new Bundle[0];
    }

    @Override
    public String getProperty(final String s) {
        // no mock implementation, simulate that no property is found and return null
        return null;
    }
    
    @Override
    public File getDataFile(final String path) {
        if (path == null) {
            throw new IllegalArgumentException("Invalid path: " + path);
        }
        synchronized (this) {
            if (dataFileBaseDir == null) {
                dataFileBaseDir = Files.createTempDir();
            }
        }
        if (path.isEmpty()) { 
            return dataFileBaseDir;
        }
        else {
            return new File(dataFileBaseDir, path);
        }
    }

    /**
     * Deactivates all bundles registered in this mocked bundle context.
     */
    @SuppressWarnings("null")
    public void shutdown() {
        for (MockServiceRegistration<?> serviceRegistration : ImmutableList.copyOf(registeredServices).reverse()) {
            try {
                MockOsgi.deactivate(serviceRegistration.getService(), this, serviceRegistration.getProperties());
            }
            catch (NoScrMetadataException ex) {
                // ignore, no deactivate method is available then
            }
        }
        if (dataFileBaseDir != null) {
            try {
                FileUtils.deleteDirectory(dataFileBaseDir);
            } catch (IOException e) {
                // ignore
            }
        }
    }

    @Override
    public Bundle getBundle(final long bundleId) {
        if (bundleId == Constants.SYSTEM_BUNDLE_ID) {
            return systemBundle;
        }
        // otherwise return null - no bundle found
        return null;
    }

    @Override
    public Bundle getBundle(String location) {
        if (StringUtils.equals(location, Constants.SYSTEM_BUNDLE_LOCATION)) {
            return systemBundle;
        }
        // otherwise return null - no bundle found
        return null;
    }

    // --- unsupported operations ---
    @Override
    public Bundle installBundle(final String s) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Bundle installBundle(final String s, final InputStream inputStream) {
        throw new UnsupportedOperationException();
    }

    @Override
    public <S> ServiceObjects<S> getServiceObjects(ServiceReference<S> reference) {
        throw new UnsupportedOperationException();
    }

}
