/**
 * 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.aries.spifly;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.BundleWire;
import org.osgi.framework.wiring.BundleWiring;
import org.osgi.util.tracker.BundleTracker;

import aQute.bnd.header.Parameters;
import aQute.bnd.stream.MapStream;
import aQute.libg.glob.Glob;

public abstract class BaseActivator implements BundleActivator {
    private static final Set<WeavingData> NON_WOVEN_BUNDLE = Collections.emptySet();
    private static final Logger logger = Logger.getLogger(BaseActivator.class.getName());

    // Static access to the activator used by the woven code, therefore
    // this bundle must be a singleton.
    // TODO see if we can get rid of the static access.
    public static BaseActivator activator;

    private BundleContext bundleContext;
    @SuppressWarnings("rawtypes")
    private BundleTracker consumerBundleTracker;
    @SuppressWarnings("rawtypes")
    private BundleTracker providerBundleTracker;
    private Optional<Parameters> autoConsumerInstructions;
    private Optional<Parameters> autoProviderInstructions;

    private final ConcurrentMap<Bundle, Set<WeavingData>> bundleWeavingData =
        new ConcurrentHashMap<Bundle, Set<WeavingData>>();

    private final ConcurrentMap<String, SortedMap<Long, Pair<Bundle, Map<String, Object>>>> registeredProviders =
            new ConcurrentHashMap<String, SortedMap<Long, Pair<Bundle, Map<String, Object>>>>();

    private final ConcurrentMap<Bundle, Map<ConsumerRestriction, List<BundleDescriptor>>> consumerRestrictions =
            new ConcurrentHashMap<Bundle, Map<ConsumerRestriction, List<BundleDescriptor>>>();

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public synchronized void start(BundleContext context, final String consumerHeaderName) throws Exception {
        bundleContext = context;

        try {
        autoConsumerInstructions = Optional.ofNullable(
            bundleContext.getProperty("org.apache.aries.spifly.auto.consumers")
        ).map(Parameters::new);

        autoProviderInstructions = Optional.ofNullable(
            bundleContext.getProperty("org.apache.aries.spifly.auto.providers")
        ).map(Parameters::new);
        }
        catch (Throwable t) {
            logger.log(Level.SEVERE, t.getMessage(), t);
        }

        providerBundleTracker = new BundleTracker(context,
                Bundle.ACTIVE, new ProviderBundleTrackerCustomizer(this, context.getBundle()));
        providerBundleTracker.open();

        consumerBundleTracker = new BundleTracker(context,
                Bundle.INSTALLED | Bundle.RESOLVED | Bundle.STARTING | Bundle.ACTIVE, new ConsumerBundleTrackerCustomizer(this, consumerHeaderName));
        consumerBundleTracker.open();

        for (Bundle bundle : context.getBundles()) {
            addConsumerWeavingData(bundle, consumerHeaderName);
        }

        activator = this;
    }

    public void addConsumerWeavingData(Bundle bundle, String consumerHeaderName) throws Exception {
        if (bundleWeavingData.containsKey(bundle)) {
            // This bundle was already processed
            return;
        }

        Map<String, List<String>> allHeaders = new HashMap<String, List<String>>();
        Set<String> addedHeaders = new HashSet<String>();
        List<String> added = allHeaders.put(consumerHeaderName, getAllHeaders(consumerHeaderName, bundle));
        if (added != null) {
            added.stream().forEach(addedHeaders::add);
        }
        added = allHeaders.put(SpiFlyConstants.REQUIRE_CAPABILITY, getAllHeaders(SpiFlyConstants.REQUIRE_CAPABILITY, bundle));
        if (added != null) {
            added.stream().forEach(addedHeaders::add);
        }
        if (addedHeaders.isEmpty()) {
            getAutoConsumerInstructions().map(Parameters::stream).orElseGet(MapStream::empty).filterKey(
                i -> Glob.toPattern(i).asPredicate().test(bundle.getSymbolicName())
            ).findFirst().ifPresent(
                un -> allHeaders.put(
                    SpiFlyConstants.REQUIRE_CAPABILITY,
                    Arrays.asList(
                        SpiFlyConstants.CLIENT_REQUIREMENT.concat(",osgi.serviceloader;filter:='(osgi.serviceloader=*)'")))
            );
        }

        Set<WeavingData> wd = new HashSet<WeavingData>();
        for (Map.Entry<String, List<String>> entry : allHeaders.entrySet()) {
            String headerName = entry.getKey();
            for (String headerVal : entry.getValue()) {
                wd.addAll(ConsumerHeaderProcessor.processHeader(headerName, headerVal));
            }
        }

        if (!wd.isEmpty()) {
            bundleWeavingData.put(bundle, Collections.unmodifiableSet(wd));

            for (WeavingData w : wd) {
                registerConsumerBundle(bundle, w.getArgRestrictions(), w.getAllowedBundles());
            }
        } else {
            bundleWeavingData.put(bundle, NON_WOVEN_BUNDLE);
        }
    }

    private List<String> getAllHeaders(String headerName, Bundle bundle) {
        List<Bundle> bundlesFragments = new ArrayList<Bundle>();
        bundlesFragments.add(bundle);

        BundleRevision rev = bundle.adapt(BundleRevision.class);
        if (rev != null) {
            BundleWiring wiring = rev.getWiring();
            if (wiring != null) {
                for (BundleWire wire : wiring.getProvidedWires("osgi.wiring.host")) {
                    bundlesFragments.add(wire.getRequirement().getRevision().getBundle());
                }
            }
        }

        List<String> l = new ArrayList<String>();
        for (Bundle bf : bundlesFragments) {
            String header = bf.getHeaders().get(headerName);
            if (header != null) {
                l.add(header);
            }
        }

        return l;
    }

    public void removeWeavingData(Bundle bundle) {
        bundleWeavingData.remove(bundle);
    }

    @Override
    public synchronized void stop(BundleContext context) throws Exception {
        activator = null;

        consumerBundleTracker.close();
        providerBundleTracker.close();
    }

    public boolean isLogEnabled(Level level) {
        return logger.isLoggable(level);
    }

    public void log(int level, String message) {
        log(level, message, null);
    }

    public void log(Level level, String message) {
        log(level, message, null);
    }

    public void log(int level, String message, Throwable th) {
        Level levelObject;

        if (Level.ALL.intValue() == level) {
            levelObject = Level.ALL;
        }
        else if (Level.CONFIG.intValue() == level) {
            levelObject = Level.CONFIG;
        }
        else if (Level.FINE.intValue() == level) {
            levelObject = Level.FINE;
        }
        else if (Level.FINER.intValue() == level) {
            levelObject = Level.FINER;
        }
        else if (Level.FINEST.intValue() == level) {
            levelObject = Level.FINEST;
        }
        else if (Level.INFO.intValue() == level) {
            levelObject = Level.INFO;
        }
        else if (Level.SEVERE.intValue() == level) {
            levelObject = Level.SEVERE;
        }
        else if (Level.WARNING.intValue() == level) {
            levelObject = Level.WARNING;
        }
        else {
            levelObject = Level.OFF;
        }

        log(levelObject, message, th);
    }

    public void log(Level level, String message, Throwable th) {
        logger.log(level, message, th);
    }

    public Set<WeavingData> getWeavingData(Bundle b) {
        // Simply return the value as it's already an immutable set.
        Set<WeavingData> wd = bundleWeavingData.get(b);
        if (wd == null)
            return null;

        if (wd.size() == 0)
            return null;

        return wd;
    }

    public void registerProviderBundle(String registrationClassName, Bundle bundle, Map<String, Object> customAttributes) {
        SortedMap<Long, Pair<Bundle, Map<String, Object>>> map = registeredProviders.computeIfAbsent(registrationClassName,
            k -> Collections.synchronizedSortedMap(new TreeMap<Long, Pair<Bundle, Map<String, Object>>>()));

        map.compute(
            bundle.getBundleId(),
            (k,v) -> {
                if (v == null) {
                    return new Pair<Bundle, Map<String, Object>>(bundle, customAttributes);
                }
                else {
                    v.getRight().putAll(customAttributes);
                    return v;
                }
            });
    }

    public void unregisterProviderBundle(Bundle bundle) {
        for (Map<Long, Pair<Bundle, Map<String, Object>>> value : registeredProviders.values()) {
            for(Iterator<Entry<Long, Pair<Bundle, Map<String, Object>>>> it = value.entrySet().iterator(); it.hasNext(); ) {
                Entry<Long, Pair<Bundle, Map<String, Object>>> entry = it.next();
                if (entry.getValue().getLeft().equals(bundle)) {
                    it.remove();
                }
            }
        }
    }

    public Collection<Bundle> findProviderBundles(String name) {
        SortedMap<Long, Pair<Bundle, Map<String, Object>>> map = registeredProviders.get(name);
        if (map == null)
            return Collections.emptyList();

        List<Bundle> bundles = new ArrayList<Bundle>(map.size());
        for(Pair<Bundle, Map<String, Object>> value : map.values()) {
            bundles.add(value.getLeft());
        }

        return bundles;
    }

    public Map<String, Object> getCustomBundleAttributes(String name, Bundle b) {
        SortedMap<Long, Pair<Bundle, Map<String, Object>>> map = registeredProviders.get(name);
        if (map == null)
            return Collections.emptyMap();

        Pair<Bundle, Map<String, Object>> data = map.get(b.getBundleId());
        if (data == null)
            return Collections.emptyMap();

        return data.getRight();
    }

    public void registerConsumerBundle(Bundle consumerBundle,
            Set<ConsumerRestriction> restrictions, List<BundleDescriptor> allowedBundles) {
        consumerRestrictions.putIfAbsent(consumerBundle, new HashMap<ConsumerRestriction, List<BundleDescriptor>>());
        Map<ConsumerRestriction, List<BundleDescriptor>> map = consumerRestrictions.get(consumerBundle);
        for (ConsumerRestriction restriction : restrictions) {
            map.put(restriction, allowedBundles);
        }
    }

    public Collection<Bundle> findConsumerRestrictions(Bundle consumer, String className, String methodName,
            Map<Pair<Integer, String>, String> args) {
        Map<ConsumerRestriction, List<BundleDescriptor>> restrictions = consumerRestrictions.get(consumer);
        if (restrictions == null) {
            // Null means: no restrictions
            return null;
        }

        for (Map.Entry<ConsumerRestriction, List<BundleDescriptor>> entry : restrictions.entrySet()) {
            if (entry.getKey().matches(className, methodName, args)) {
                return getBundles(entry.getValue(), className, methodName, args);
            }
        }

        // Empty collection: nothing matches
        return Collections.emptySet();
    }

    public Optional<Parameters> getAutoConsumerInstructions() {
        if (autoConsumerInstructions == null) return Optional.empty();
        return autoConsumerInstructions;
    }

    public void setAutoConsumerInstructions(Optional<Parameters> autoConsumerInstructions) {
        this.autoConsumerInstructions = autoConsumerInstructions;
    }

    public Optional<Parameters> getAutoProviderInstructions() {
        if (autoProviderInstructions == null) return Optional.empty();
        return autoProviderInstructions;
    }

    public void setAutoProviderInstructions(Optional<Parameters> autoProviderInstructions) {
        this.autoProviderInstructions = autoProviderInstructions;
    }

    private Collection<Bundle> getBundles(List<BundleDescriptor> descriptors, String className, String methodName,
            Map<Pair<Integer, String>, String> args) {
        if (descriptors == null) {
            return null;
        }

        List<Bundle> bundles = new ArrayList<Bundle>();
        for (Bundle b : bundleContext.getBundles()) {
            for (BundleDescriptor desc : descriptors) {
                if (desc.getBundleID() != BundleDescriptor.BUNDLE_ID_UNSPECIFIED) {
                    if (b.getBundleId() == desc.getBundleID()) {
                        bundles.add(b);
                    }
                } else if (desc.getFilter() != null) {
                    Hashtable<String, Object> d = new Hashtable<String, Object>();

                    if (ServiceLoader.class.getName().equals(className) &&
                        "load".equals(methodName)) {
                        String type = args.get(new Pair<Integer, String>(0, Class.class.getName()));
                        if (type != null) {
                            d.put(SpiFlyConstants.SERVICELOADER_CAPABILITY_NAMESPACE, type);
                            d.putAll(getCustomBundleAttributes(type, b));
                        }
                    }
                    if (desc.getFilter().match(d))
                        bundles.add(b);
                } else {
                    if (b.getSymbolicName().equals(desc.getSymbolicName())) {
                        if (desc.getVersion() == null || b.getVersion().equals(desc.getVersion())) {
                            bundles.add(b);
                        }
                    }
                }
            }
        }
        return bundles;
    }

}
