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

import org.osgi.framework.Bundle;
import org.osgi.framework.Version;
import org.osgi.framework.hooks.resolver.ResolverHook;
import org.osgi.framework.namespace.PackageNamespace;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleRequirement;
import org.osgi.framework.wiring.BundleRevision;

import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Level;

class ResolverHookImpl implements ResolverHook {
    final Map<Map.Entry<String, Version>, List<String>> bsnVerMap;
    final Map<String, Set<String>> bundleFeatureMap;
    final Map<String, Set<String>> featureRegionMap;
    final Map<String, Set<String>> regionPackageMap;
    final Set<String> defaultRegions;

    ResolverHookImpl(Map<Entry<String, Version>, List<String>> bsnVerMap, Map<String, Set<String>> bundleFeatureMap,
            Map<String, Set<String>> featureRegionMap, Map<String, Set<String>> regionPackageMap, Set<String> defaultRegions) {
        this.bsnVerMap = bsnVerMap;
        this.bundleFeatureMap = bundleFeatureMap;
        this.featureRegionMap = featureRegionMap;
        this.regionPackageMap = regionPackageMap;
        this.defaultRegions = defaultRegions;
    }

    @Override
    public void filterResolvable(Collection<BundleRevision> candidates) {
        // Nothing to do
    }

    @Override
    public void filterSingletonCollisions(BundleCapability singleton, Collection<BundleCapability> collisionCandidates) {
        // Nothing to do
    }

    @Override
    public void filterMatches(BundleRequirement requirement, Collection<BundleCapability> candidates) {
        // Filtering is only on package resolution. Any other kind of resolution is not limited
        if (!PackageNamespace.PACKAGE_NAMESPACE.equals(requirement.getNamespace()))
            return;

        Bundle reqBundle = requirement.getRevision().getBundle();
        long reqBundleID = reqBundle.getBundleId();
        String reqBundleName = reqBundle.getSymbolicName();
        Version reqBundleVersion = reqBundle.getVersion();

        Set<String> reqRegions = new HashSet<>(defaultRegions);
        List<String> reqFeatures = new ArrayList<>();
        List<String> aids = bsnVerMap.get(new AbstractMap.SimpleEntry<String, Version>(reqBundleName, reqBundleVersion));
        if (aids != null) {
            for (String aid : aids) {
                Set<String> fid = bundleFeatureMap.get(aid);
                if (fid != null)
                    reqFeatures.addAll(fid);
            }

            for (String feature : reqFeatures) {
                Set<String> fr = featureRegionMap.get(feature);
                if (fr != null) {
                    reqRegions.addAll(fr);
                }
            }
        } else {
            // Bundle is not coming from a feature
        }

        Set<BundleCapability> coveredCaps = new HashSet<>();

        Map<BundleCapability, String> bcFeatureMap = new HashMap<>();
        String packageName = null;
        nextCapability:
        for (BundleCapability bc : candidates) {
            BundleRevision rev = bc.getRevision();

            Bundle capBundle = rev.getBundle();
            long capBundleID = capBundle.getBundleId();
            if (capBundleID == 0) {
                // always allow capability from the system bundle
                coveredCaps.add(bc);
                continue nextCapability;
            }

            if (capBundleID == reqBundleID) {
                // always allow capability from same bundle
                coveredCaps.add(bc);
                continue nextCapability;
            }

            String capBundleName = capBundle.getSymbolicName();
            Version capBundleVersion = capBundle.getVersion();

            List<String> capBundleArtifacts = bsnVerMap.get(new AbstractMap.SimpleEntry<String, Version>(capBundleName, capBundleVersion));
            if (capBundleArtifacts == null) {
                // Capability is not in any feature, everyone can access
                coveredCaps.add(bc);
                continue nextCapability;
            }

            List<String> capFeatures = new ArrayList<>();
            for (String ba : capBundleArtifacts) {
                Set<String> capfeats = bundleFeatureMap.get(ba);
                if (capfeats != null)
                    capFeatures.addAll(capfeats);
            }

            if (capFeatures.isEmpty())
                capFeatures = Collections.singletonList(null);

            for (String capFeat : capFeatures) {
                if (capFeat == null) {
                    // always allow capability not coming from a feature
                    coveredCaps.add(bc);
                    continue nextCapability;
                }

                if (reqFeatures.contains(capFeat)) {
                    // Within a single feature everything can wire to everything else
                    coveredCaps.add(bc);
                    continue nextCapability;
                }

                Set<String> capRegions = featureRegionMap.get(capFeat);
                if (capRegions == null) {
                    // If the feature hosting the capability has no regions defined, everyone can access
                    coveredCaps.add(bc);
                    continue nextCapability;
                }
                bcFeatureMap.put(bc, capFeat);

                List<String> sharedRegions = new ArrayList<>(reqRegions);
                sharedRegions.retainAll(capRegions);

                // Add any regions before the sharedRegions back in, as later regions inherit from earlier ones
                List<String> capRegionList = new ArrayList<>(capRegions);
                for (String region : new ArrayList<>(sharedRegions)) {
                    boolean foundRegion = false;
                    for (int i = capRegionList.size() - 1; i >= 0; i--) {
                        String capRegion = capRegionList.get(i);
                        if (region.equals(capRegion)) {
                            foundRegion = true;
                            continue;
                        }
                        if (foundRegion) {
                            // Add the found region to the front of the list of shared regions
                            sharedRegions.add(0, capRegion);
                        }
                    }
                }

                Object pkg = bc.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE);
                if (pkg instanceof String) {
                    packageName = (String) pkg;

                    Set<String> globalPackages = regionPackageMap.get(RegionEnforcer.GLOBAL_REGION);
                    if (globalPackages != null && globalPackages.contains(packageName)) {
                        // If the export is in the global region everyone can access
                        coveredCaps.add(bc);
                        continue nextCapability;
                    }

                    for (String region : sharedRegions) {
                        Set<String> regionPackages = regionPackageMap.get(region);
                        if (regionPackages != null && regionPackages.contains(packageName)) {
                            // If the export is in a region that the feature is also in, then allow
                            coveredCaps.add(bc);
                            continue nextCapability;
                        }
                    }
                }
            }
        }

        List<BundleCapability> removedCandidates = new ArrayList<>(candidates);
        // Remove any capabilities that are not covered
        candidates.retainAll(coveredCaps);

        if (candidates.isEmpty()) {
            removedCandidates.removeAll(candidates);

            StringBuilder sb = new StringBuilder();
            boolean first = true;
            for (BundleCapability bc : removedCandidates) {
                if (first)
                    first = false;
                else
                    sb.append(", ");

                sb.append(bc.toString());
                sb.append("[Regions: ");
                sb.append(getRegionsForPackage(packageName, bcFeatureMap.get(bc)));
                sb.append("]");
            }

            RegionEnforcer.LOG.log(Level.WARNING,
                    "API-Regions removed candidates {0} for requirement {1} as the requirement is in the following regions: {2}",
                    new Object[] {sb, requirement, reqRegions});
        }
    }

    List<String> getRegionsForPackage(String packageName, String feature) {
        if (packageName == null)
            return Collections.emptyList();

        Set<String> regions = featureRegionMap.get(feature);
        if (regions == null)
            return Collections.emptyList();

        List<String> res = new ArrayList<>();
        boolean found = false;
        for (String region : regions) {
            Set<String> packages = regionPackageMap.get(region);
            if (packages == null)
                continue;

            if (found) {
                // Since later regions inherit from earlier ones, if the package has been found before
                // it also applies to this region.
                res.add(region);
            } else if (packages.contains(packageName)) {
                res.add(region);
                found = true;
            }
        }
        return res;
    }

    @Override
    public void end() {
        // Nothing to do
    }
}
