/*
 * 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.extension.apiregions.analyser;

import org.apache.sling.feature.ArtifactId;
import org.apache.sling.feature.analyser.task.AnalyserTaskContext;
import org.apache.sling.feature.extension.apiregions.api.ApiExport;
import org.apache.sling.feature.extension.apiregions.api.ApiRegion;
import org.apache.sling.feature.extension.apiregions.api.ApiRegions;
import org.apache.sling.feature.scanner.BundleDescriptor;
import org.apache.sling.feature.scanner.FeatureDescriptor;
import org.apache.sling.feature.scanner.PackageInfo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public class CheckApiRegionsCrossFeatureDups extends AbstractApiRegionsAnalyserTask {

    @Override
    public String getId() {
        return ApiRegions.EXTENSION_NAME + "-crossfeature-dups";
    }

    @Override
    public String getName() {
        return "Api Regions cross-feature duplicate export task";
    }

    @Override
    protected void execute(ApiRegions apiRegions, AnalyserTaskContext ctx) throws Exception {
        Set<String> checkedRegions = splitListConfig(ctx.getConfiguration().get("regions"));
        Set<String> ignoredPackages = splitListConfig(ctx.getConfiguration().get("ignoredPackages"));
        Set<String> warningPackages = splitListConfig(ctx.getConfiguration().get("warningPackages"));
        Set<String> definingFeatures = splitListConfig(ctx.getConfiguration().get("definingFeatures"));

        Map<String, Set<String>> regionExports = new HashMap<>();
        Set<ArtifactId> apiRegionsFeatures = new HashSet<>();

        for (ApiRegion r : apiRegions.listRegions()) {
            apiRegionsFeatures.addAll(Arrays.asList(r.getFeatureOrigins()));
            if (checkedRegions.isEmpty() || checkedRegions.contains(r.getName())) {
                Set<String> exports = regionExports.get(r.getName());
                if (exports == null) {
                    exports = new HashSet<>();
                    regionExports.put(r.getName(), exports);
                }
                exports.addAll(r.listExports().stream().map(ApiExport::getName).collect(Collectors.toSet()));
            }
        }

        if (definingFeatures.isEmpty()) {
            definingFeatures = apiRegionsFeatures
                    .stream()
                    .map(ArtifactId::toMvnId)
                    .collect(Collectors.toSet());
        }

        FeatureDescriptor f = ctx.getFeatureDescriptor();
        for (BundleDescriptor bd : f.getBundleDescriptors()) {
            List<ArtifactId> borgs = new ArrayList<>(Arrays.asList(bd.getArtifact().getFeatureOrigins()));
            removeDefiningFeatures(definingFeatures, borgs);

            if (!borgs.isEmpty()) {
                Set<String> reportedPackages = new HashSet<>();
                for (PackageInfo pi : bd.getExportedPackages()) {
                    String pkgName = pi.getName();
                    for (Map.Entry<String, Set<String>> entry : regionExports.entrySet()) {
                        if (entry.getValue().contains(pkgName) && !reportedPackages.contains(pkgName)) {
                            if (matchesSet(pkgName, ignoredPackages)) {
                                continue;
                            }

                            if (allOtherExportersNonDefining(pi, f, definingFeatures)) {
                                // If all exports are done by non-defining features then that's ok
                                continue;
                            }

                            reportedPackages.add(pi.getName());

                            String msg = "Package overlap found between region " + entry.getKey()
                                + " and bundle " + bd.getBundleSymbolicName() + " " + bd.getBundleVersion()
                                + " which comes from feature: " + borgs
                                + ". Both export package: " + pi.getName();
                            if (matchesSet(pkgName, warningPackages)) {
                                ctx.reportArtifactWarning(bd.getArtifact().getId(), msg);
                            } else {
                                ctx.reportArtifactError(bd.getArtifact().getId(), msg);
                            }
                        }
                    }
                }
            }
        }
    }

    // Check if all exports of this package are done by non-defining features
    private boolean allOtherExportersNonDefining(PackageInfo pi, FeatureDescriptor f, Set<String> definingFeatures) {
        List<ArtifactId> declaringFeatures = new ArrayList<>();

        for (BundleDescriptor bd : f.getBundleDescriptors()) {
            if (bd.getExportedPackages().contains(pi)) {
                declaringFeatures.addAll(Arrays.asList(bd.getArtifact().getFeatureOrigins(f.getFeature().getId())));
            }
        }

        for (ArtifactId feature : declaringFeatures) {
            for (String definingFeature : definingFeatures) {
                if (definingFeature.endsWith("*")) {
                    String prefix = definingFeature.substring(0, definingFeature.length() - 1);
                    if (feature.toMvnId().startsWith(prefix)) {
                        return false;
                    }
                } else {
                    if (feature.toMvnId().equals(definingFeature)) {
                        return false;
                    }
                }
            }
        }
        return true;
    }

    private void removeDefiningFeatures(Set<String> definingFeatures, List<ArtifactId> features) {
        for (Iterator<ArtifactId> it = features.iterator(); it.hasNext(); ) {
            ArtifactId feature = it.next();
            for (String definingFeature : definingFeatures) {
                if (definingFeature.endsWith("*")) {
                    String prefix = definingFeature.substring(0, definingFeature.length() - 1);
                    if (feature.toMvnId().startsWith(prefix)) {
                        it.remove();
                    }
                } else {
                    if (feature.toMvnId().equals(definingFeature)) {
                        it.remove();
                    }
                }
            }
        }
    }

    private boolean matchesSet(String pkg, Set<String> set) {
        for (String e : set) {
            if (e.endsWith("*")) {
                if (pkg.startsWith(e.substring(0, e.length() - 1)) ) {
                    return true;
                }
            } else {
                if (pkg.equals(e)) {
                    return true;
                }
            }
        }
        return false;
    }

    private Set<String> splitListConfig(String value) {
        if (value == null) {
            return Collections.emptySet();
        } else {
            return Arrays.asList(value.split(","))
                .stream()
                .map(String::trim)
                .collect(Collectors.toSet());
        }
    }
}
