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

import static java.util.Objects.requireNonNull;
import static org.apache.sling.feature.cpconverter.vltpkg.VaultPackageUtils.detectPackageType;
import static org.apache.sling.feature.cpconverter.vltpkg.VaultPackageUtils.getDependencies;

import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;

import org.apache.commons.io.FileUtils;
import org.apache.jackrabbit.vault.fs.io.Archive;
import org.apache.jackrabbit.vault.fs.io.Archive.Entry;
import org.apache.jackrabbit.vault.packaging.Dependency;
import org.apache.jackrabbit.vault.packaging.PackageId;
import org.apache.jackrabbit.vault.packaging.PackageProperties;
import org.apache.jackrabbit.vault.packaging.PackageType;
import org.apache.jackrabbit.vault.packaging.VaultPackage;
import org.apache.sling.feature.ArtifactId;
import org.apache.sling.feature.cpconverter.accesscontrol.AclManager;
import org.apache.sling.feature.cpconverter.artifacts.ArtifactsDeployer;
import org.apache.sling.feature.cpconverter.artifacts.FileArtifactWriter;
import org.apache.sling.feature.cpconverter.features.FeaturesManager;
import org.apache.sling.feature.cpconverter.filtering.ResourceFilter;
import org.apache.sling.feature.cpconverter.handlers.DefaultHandler;
import org.apache.sling.feature.cpconverter.handlers.EntryHandler;
import org.apache.sling.feature.cpconverter.handlers.EntryHandlersManager;
import org.apache.sling.feature.cpconverter.handlers.NodeTypesEntryHandler;
import org.apache.sling.feature.cpconverter.vltpkg.BaseVaultPackageScanner;
import org.apache.sling.feature.cpconverter.vltpkg.PackagesEventsEmitter;
import org.apache.sling.feature.cpconverter.vltpkg.RecollectorVaultPackageScanner;
import org.apache.sling.feature.cpconverter.vltpkg.VaultPackageAssembler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public class ContentPackage2FeatureModelConverter extends BaseVaultPackageScanner implements Closeable {

    public static final String ZIP_TYPE = "zip";

    public static final String PACKAGE_CLASSIFIER = "cp2fm-converted";

    private static final String DEFAULT_VERSION = "0.0.0";

    private final Map<PackageId, String> subContentPackages = new HashMap<>();

    private final List<VaultPackageAssembler> assemblers = new LinkedList<>();

    private final Map<PackageId, Set<Dependency>> mutableContentsIds = new LinkedHashMap<>();

    private EntryHandlersManager handlersManager;

    private AclManager aclManager;

    private FeaturesManager featuresManager;

    private ResourceFilter resourceFilter;

    private ArtifactsDeployer artifactsDeployer;

    private ArtifactsDeployer unreferencedArtifactsDeployer;

    private VaultPackageAssembler mainPackageAssembler;

    private final RecollectorVaultPackageScanner recollectorVaultPackageScanner;

    private final List<PackagesEventsEmitter> emitters = new ArrayList<>();

    private final List<Runnable> deployTasks = new ArrayList<>();

    private final File tmpDirectory;

    private boolean failOnMixedPackages = false;

    private PackagePolicy contentTypePackagePolicy = PackagePolicy.REFERENCE;

    private boolean removeInstallHooks = false;

    public enum PackagePolicy {
        /**
         * References the content package in the feature model and deploys via the {@link ContentPackage2FeatureModelConverter#artifactsDeployer}
         */
        REFERENCE,
        /**
         * Drops the content package completely (i.e. neither reference it in the feature model nor deploy anywhere)
         *
         * @deprecated
         */
        DROP,
        /**
         * Deploys the content package via the {@link ContentPackage2FeatureModelConverter#unreferencedArtifactsDeployer}
         */
        PUT_IN_DEDICATED_FOLDER
    }

    public enum SlingInitialContentPolicy {
        /**
         * Keep in bundle and don't extract
         */
        KEEP,
        /**
         * Extract from bundle into content-packages and feature model
         */
        EXTRACT_AND_REMOVE,
        /**
         * Extract from bundle into content-packages and feature model but keep in bundle as well
         */
        EXTRACT_AND_KEEP
    }

    public ContentPackage2FeatureModelConverter() throws IOException {
        this(false, SlingInitialContentPolicy.KEEP);
    }

    public ContentPackage2FeatureModelConverter(boolean strictValidation, @NotNull SlingInitialContentPolicy slingInitialContentPolicy) throws IOException {
        super(strictValidation);
        this.recollectorVaultPackageScanner = new RecollectorVaultPackageScanner(this, this.packageManager, strictValidation, subContentPackages, slingInitialContentPolicy);
        this.tmpDirectory = Files.createTempDirectory("cp2fm-converter").toFile();
    }

    public @NotNull ContentPackage2FeatureModelConverter setEntryHandlersManager(@Nullable EntryHandlersManager handlersManager) {
        this.handlersManager = handlersManager;
        return this;
    }

    public @Nullable FeaturesManager getFeaturesManager() {
        return featuresManager;
    }

    public @NotNull ContentPackage2FeatureModelConverter setFeaturesManager(@NotNull FeaturesManager featuresManager) {
        this.featuresManager = featuresManager;
        if (featuresManager instanceof PackagesEventsEmitter) {
            this.emitters.add((PackagesEventsEmitter) featuresManager);
        }
        return this;
    }

    public @NotNull ContentPackage2FeatureModelConverter setResourceFilter(@Nullable ResourceFilter resourceFilter) {
        this.resourceFilter = resourceFilter;
        return this;
    }

    public @Nullable ArtifactsDeployer getArtifactsDeployer() {
        return artifactsDeployer;
    }

    public @NotNull ContentPackage2FeatureModelConverter setBundlesDeployer(@NotNull ArtifactsDeployer bundlesDeployer) {
        this.artifactsDeployer = bundlesDeployer;
        return this;
    }

    public @NotNull ContentPackage2FeatureModelConverter setUnreferencedArtifactsDeployer(@NotNull ArtifactsDeployer unreferencedArtifactsDeployer) {
        this.unreferencedArtifactsDeployer = unreferencedArtifactsDeployer;
        return this;
    }

    public @Nullable AclManager getAclManager() {
        return aclManager;
    }

    public @NotNull ContentPackage2FeatureModelConverter setAclManager(@NotNull AclManager aclManager) {
        this.aclManager = aclManager;
        return this;
    }
    
    public boolean hasMainPackageAssembler() {
        return mainPackageAssembler != null;
    }

    public @NotNull VaultPackageAssembler getMainPackageAssembler() {
        // verify that mainPackageAssembler has been set before retrieving it
        return Objects.requireNonNull(mainPackageAssembler);
    }

    public @NotNull ContentPackage2FeatureModelConverter setMainPackageAssembler(@NotNull VaultPackageAssembler assembler) {
        this.mainPackageAssembler = assembler;
        return this;
    }

    public @NotNull ContentPackage2FeatureModelConverter setEmitter(@NotNull PackagesEventsEmitter emitter) {
        this.emitters.add(emitter);
        return this;
    }

    public @NotNull ContentPackage2FeatureModelConverter setContentTypePackagePolicy(@NotNull PackagePolicy contentTypePackagePolicy) {
        this.contentTypePackagePolicy = contentTypePackagePolicy;
        return this;
    }

    public @NotNull ContentPackage2FeatureModelConverter setFailOnMixedPackages(boolean failOnMixedPackages) {
        this.failOnMixedPackages = failOnMixedPackages;
        return this;
    }

    public @NotNull ContentPackage2FeatureModelConverter setRemoveInstallHooks(boolean removeInstallHook) {
        this.removeInstallHooks = removeInstallHook;
        return this;
    }

    public @NotNull File getTempDirectory() {
        return this.tmpDirectory;
    }
    
    public void cleanup() throws IOException {
        if (this.tmpDirectory.exists()) {
            logger.info("Cleaning up tmp directory {}", this.tmpDirectory);

            FileUtils.deleteDirectory(this.tmpDirectory);
        }
    }

    public void convert(@NotNull File... contentPackages) throws IOException, ConverterException {
        requireNonNull(contentPackages, "Null content-package(s) can not be converted.");
        secondPass(firstPass(contentPackages));
    }

    protected @NotNull Collection<VaultPackage> firstPass(@NotNull File... contentPackages) throws IOException, ConverterException {
        Map<PackageId, VaultPackage> idFileMap = new LinkedHashMap<>();
        Map<PackageId, VaultPackage> idPackageMapping = new ConcurrentHashMap<>();

        for (File contentPackage : contentPackages) {
            requireNonNull(contentPackage, "Null content-package can not be converted.");

            if (!contentPackage.exists() || !contentPackage.isFile()) {
                throw new IllegalArgumentException("File " + contentPackage + " does not exist or it is a directory");
            }

            logger.info("Reading content-package '{}'...", contentPackage);

            VaultPackage pack = open(contentPackage);
            idPackageMapping.put(pack.getId(), pack);

            // analyze sub-content packages in order to filter out
            // possible outdated conflicting packages
            recollectorVaultPackageScanner.traverse(pack);

            logger.info("content-package '{}' successfully read!", contentPackage);
        }

        logger.info("Ordering input content-package(s) {}...", idPackageMapping.keySet());

        for (VaultPackage pack : idPackageMapping.values()) {
            orderDependencies(idFileMap, idPackageMapping, pack, new HashSet<>());
        }

        logger.info("New content-package(s) order: {}", idFileMap.keySet());

        return idFileMap.values();
    }

    private void secondPass(@NotNull Collection<VaultPackage> orderedContentPackages) throws IOException, ConverterException {
        emitters.stream().forEach(PackagesEventsEmitter::start);

        for (VaultPackage vaultPackage : orderedContentPackages) {
            try {
                emitters.stream().forEach(e -> e.startPackage(vaultPackage));
                setMainPackageAssembler(VaultPackageAssembler.create(this.getTempDirectory(), vaultPackage, removeInstallHooks));
                assemblers.add(getMainPackageAssembler());

                ArtifactId mvnPackageId = toArtifactId(vaultPackage.getId(), vaultPackage.getFile());

                featuresManager.init(mvnPackageId.getGroupId(), mvnPackageId.getArtifactId(), mvnPackageId.getVersion());

                logger.info("Converting content-package '{}'...", vaultPackage.getId());

                traverse(vaultPackage);

                // retrieve the resulting zip-content-package and deploy it to the local mvn bundles dir.
                try (VaultPackage result = processContentPackageArchive(getMainPackageAssembler(), null)) {

                    // finally serialize the Feature Model(s) file(s)

                    aclManager.addRepoinitExtension(assemblers, featuresManager);

                    logger.info("Conversion complete!");

                    featuresManager.serialize();

                    emitters.stream().forEach(e -> e.endPackage(vaultPackage.getId(), result));
                }
            } finally {
                aclManager.reset();
                assemblers.clear();

                try {
                    vaultPackage.close();
                } catch (Exception e) {
                    // close quietly
                }
            }
        }

        deployPackages();
        mutableContentsIds.clear();

        emitters.stream().forEach(PackagesEventsEmitter::end);
    }

    private static void orderDependencies(@NotNull Map<PackageId, VaultPackage> idFileMap,
                                          @NotNull Map<PackageId, VaultPackage> idPackageMapping,
                                          @NotNull VaultPackage pack,
                                          @NotNull Set<PackageId> visited) throws IOException, ConverterException {
        if (!visited.add(pack.getId())) {
            throw new ConverterException("Cyclic dependency detected, " + pack.getId() + " was previously visited already");
        }

        for (Dependency dep : pack.getDependencies()) {
            for (java.util.Map.Entry<PackageId, VaultPackage> entry : idPackageMapping.entrySet()) {
                if (dep.matches(entry.getKey())) {
                    orderDependencies(idFileMap, idPackageMapping, entry.getValue(), visited);
                    break;
                }
            }
        }

        idFileMap.put(pack.getId(), pack);
        idPackageMapping.remove(pack.getId());
    }

    public void processSubPackage(@NotNull String path, @Nullable String runMode, @NotNull VaultPackage vaultPackage, boolean isEmbeddedPackage) throws IOException, ConverterException {
        requireNonNull(path, "Impossible to process a null vault package");
        requireNonNull(vaultPackage, "Impossible to process a null vault package");

        if (!isSubContentPackageIncluded(path)) {
            logger.info("Sub content-package {} is filtered out, so it won't be processed.", path);
            return;
        }

        emitters.stream().forEach(e -> e.startSubPackage(path, vaultPackage));

        VaultPackageAssembler clonedPackage = VaultPackageAssembler.create(this.getTempDirectory(), vaultPackage, removeInstallHooks);

        // Please note: THIS IS A HACK to meet the new requirement without drastically change the original design
        // temporary swap the main handler to collect stuff
        VaultPackageAssembler handler = getMainPackageAssembler();
        assemblers.add(handler);
        Properties parentProps = handler.getPackageProperties();
        boolean isContainerPackage = PackageType.CONTAINER.equals(parentProps.get(PackageProperties.NAME_PACKAGE_TYPE));
        setMainPackageAssembler(clonedPackage);

        // scan the detected package, first
        traverse(vaultPackage);
        
        //set dependency to parent package if the parent package is an application package & subpackage is embedded
        if (isEmbeddedPackage && !isContainerPackage) {
            PackageId parentId = new PackageId((String) parentProps.get(PackageProperties.NAME_GROUP),
                    (String) parentProps.get(PackageProperties.NAME_NAME),
                    (String) parentProps.get(PackageProperties.NAME_VERSION));
            clonedPackage.addDependency(new Dependency(parentId));
        }

        // deploy the new content-package to the local mvn bundles dir and attach it to the feature
        try (VaultPackage result = processContentPackageArchive(clonedPackage, runMode)) {
            emitters.stream().forEach(e -> e.endSubPackage(path, vaultPackage.getId(), result));
        }

        // restore the previous assembler
        setMainPackageAssembler(handler);
    }

    private @NotNull VaultPackage processContentPackageArchive(@NotNull VaultPackageAssembler assembler,
                                             @Nullable String runMode) throws IOException, ConverterException {
        File contentPackageArchive = assembler.createPackage();

        VaultPackage vaultPackage = open(contentPackageArchive);

        PackageType packageType = detectPackageType(vaultPackage);

        // SLING-8608 - Fail the conversion if the resulting attached content-package is MIXED type
        if (PackageType.MIXED == packageType && failOnMixedPackages) {
            throw new ConverterException("Generated content-package '"
                    + vaultPackage.getId()
                    + "' located in file "
                    + contentPackageArchive
                    + " is of MIXED type");
        }

        ArtifactId mvnPackageId = toArtifactId(vaultPackage.getId(), contentPackageArchive);
        // special handling for converted packages of type content
        if (PackageType.CONTENT == packageType) {
            switch (contentTypePackagePolicy) {
                case DROP:
                    mutableContentsIds.put(vaultPackage.getId(), getDependencies(vaultPackage));
                    logger.info("Dropping package of PackageType.CONTENT {} (content-package id: {})",
                            mvnPackageId.getArtifactId(), vaultPackage.getId());
                    break;
                case PUT_IN_DEDICATED_FOLDER:
                    mutableContentsIds.put(vaultPackage.getId(), getDependencies(vaultPackage));
                    // deploy the new content-package to the unreferenced artifacts deployer
                    if (unreferencedArtifactsDeployer == null) {
                        throw new IllegalStateException("ContentTypePackagePolicy PUT_IN_DEDICATED_FOLDER requires a valid deployer ");
                    }
                    unreferencedArtifactsDeployer.deploy(new FileArtifactWriter(contentPackageArchive), mvnPackageId);
                    logger.info("Put converted package of PackageType.CONTENT {} (content-package id: {}) in {} (not referenced in feature model)",
                            mvnPackageId.getArtifactId(), vaultPackage.getId(), unreferencedArtifactsDeployer.getBaseDirectory());
                    break;
                case REFERENCE:
                    deploy(assembler, mvnPackageId, runMode);
            }
        } else {
            deploy(assembler, mvnPackageId, runMode);
        }
        return vaultPackage;
    }

    public void deployPackages() {
        try {
            mutableContentsIds.values().forEach(
                    value -> value.removeIf(dep -> mutableContentsIds.keySet().stream().anyMatch(dep::matches)));

            deployTasks.forEach(Runnable::run);
        } catch (RuntimeException ex) {
            if (ex.getCause() instanceof Exception) {
                throw ex;
            }
            throw ex;
        }
        deployTasks.clear();
    }

    private void deploy(@NotNull VaultPackageAssembler assembler, @NotNull ArtifactId mvnPackageId, @Nullable String runMode) {
        Objects.requireNonNull(getFeaturesManager()).addArtifact(runMode, mvnPackageId);
        ArtifactsDeployer deployer = Objects.requireNonNull(getArtifactsDeployer());
        deployTasks.add(() -> {
            assembler.updateDependencies(mutableContentsIds);
            try {
                File finalContentPackageArchive = assembler.createPackage();
                // deploy the new content-package to the local mvn bundles dir
                deployer.deploy(new FileArtifactWriter(finalContentPackageArchive), mvnPackageId);
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
        });
    }

    public boolean isSubContentPackageIncluded(@NotNull String path) {
        return subContentPackages.containsValue(path);
    }

    private void process(@NotNull String entryPath, @NotNull Archive archive, @Nullable Entry entry) throws IOException, ConverterException {
        if (resourceFilter != null && resourceFilter.isFilteredOut(entryPath)) {
            throw new ConverterException("Path '"
                    + entryPath
                    + "' in archive "
                    + archive.getMetaInf().getPackageProperties().getId()
                    + " not allowed by user configuration, please check configured filtering patterns");
        }

        EntryHandler entryHandler = handlersManager.getEntryHandlerByEntryPath(entryPath);
        if (entryHandler == null) {
            entryHandler = new DefaultHandler(getMainPackageAssembler(), removeInstallHooks);
        }

        if (entry == null) {
            entry = archive.getEntry(entryPath);
            if (entry == null) {
                throw new IllegalArgumentException("Archive '" + archive.getMetaInf().getPackageProperties().getId() + "' does not contain entry with path '" + entryPath + "'");
            }
        }
        entryHandler.handle(entryPath, archive, entry, this);
        if (!getMainPackageAssembler().recordEntryPath(entryPath)) {
            logger.warn("Duplicate entry path {}", entryPath);
        }
    }

    @Override
    protected void onFile(@NotNull String entryPath, @NotNull Archive archive, @NotNull Entry entry) throws IOException, ConverterException {
        process(entryPath, archive, entry);
    }

    public static @NotNull ArtifactId toArtifactId(@NotNull PackageId packageId, @NotNull File file) {
        String groupId = requireNonNull(packageId.getGroup(),
                PackageProperties.NAME_GROUP
                        + " property not found in content-package "
                        + file
                        + ", please check META-INF/vault/properties.xml").replace('/', '.');
        // Replace any space with an underscore to adhere to Maven Group Id specification
        groupId = groupId.replace(" ", "_");

        String artifactId = requireNonNull(packageId.getName(),
                PackageProperties.NAME_NAME
                        + " property not found in content-package "
                        + file
                        + ", please check META-INF/vault/properties.xml");
        // Replace any space with an underscore to adhere to Maven Artifact Id specification
        artifactId = artifactId.replace(" ", "_");

        // package versions may use suffix "-cp2fm-converted" which is redundant as for artifactIds this is set as dedicated classifier
        String version = packageId.getVersionString();
        if (version.endsWith(VaultPackageAssembler.VERSION_SUFFIX)) {
            version = version.substring(0, version.length() - VaultPackageAssembler.VERSION_SUFFIX.length());
        }
        if (version.isEmpty()) {
            version = DEFAULT_VERSION;
        }

        return new ArtifactId(groupId, artifactId, version, PACKAGE_CLASSIFIER, ZIP_TYPE);
    }

    @Override
    protected void addCdnPattern(@NotNull Pattern cndPattern) {
        handlersManager.addEntryHandler(NodeTypesEntryHandler.forCndPattern(cndPattern));
    }

    @Override
    public void close() throws IOException {
        cleanup();
    }

}
