/*
 * 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.distribution.serialization.impl.vlt;

import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;
import java.util.zip.Deflater;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.jackrabbit.vault.fs.api.ImportMode;
import org.apache.jackrabbit.vault.fs.api.PathFilterSet;
import org.apache.jackrabbit.vault.fs.api.WorkspaceFilter;
import org.apache.jackrabbit.vault.fs.config.DefaultMetaInf;
import org.apache.jackrabbit.vault.fs.config.DefaultWorkspaceFilter;
import org.apache.jackrabbit.vault.fs.config.MetaInf;
import org.apache.jackrabbit.vault.fs.filter.DefaultPathFilter;
import org.apache.jackrabbit.vault.fs.io.AccessControlHandling;
import org.apache.jackrabbit.vault.fs.io.ImportOptions;
import org.apache.jackrabbit.vault.packaging.ExportOptions;
import org.apache.jackrabbit.vault.packaging.JcrPackage;
import org.apache.jackrabbit.vault.packaging.PackageManager;
import org.apache.jackrabbit.vault.packaging.PackageProperties;
import org.apache.jackrabbit.vault.packaging.VaultPackage;
import org.apache.sling.distribution.DistributionRequest;
import org.apache.sling.distribution.DistributionRequestType;
import org.apache.sling.distribution.SimpleDistributionRequest;
import org.apache.sling.distribution.component.impl.SettingsUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Utility class for creating vlt filters and import/export options
 */
public class VltUtils {

    private final static Logger log = LoggerFactory.getLogger(VltUtils.class);

    /**
     * The custom <code>Path-Mapping</code> property.
     */
    private static final String PATH_MAPPING_PROPERTY = "Path-Mapping";

    private static final String MAPPING_SEPARATOR = "=";

    private static final String MAPPING_DELIMITER = ";";

    public static WorkspaceFilter createFilter(DistributionRequest distributionRequest, NavigableMap<String, List<String>> nodeFilters,
                                               NavigableMap<String, List<String>> propertyFilters) {
        DefaultWorkspaceFilter filter = new DefaultWorkspaceFilter();

        for (String path : distributionRequest.getPaths()) {

            // Set node path filters
            List<String> patterns = new ArrayList<String>();
            patterns.addAll(Arrays.asList(distributionRequest.getFilters(path)));
            boolean deep = distributionRequest.isDeep(path);
            PathFilterSet nodeFilterSet = new PathFilterSet(path);
            if (!deep) {
                nodeFilterSet.addInclude(new DefaultPathFilter(path));
            }
            initFilterSet(nodeFilterSet, nodeFilters, patterns);

            // Set property path filters
            PathFilterSet propertyFilterSet = new PathFilterSet("/");
            initFilterSet(propertyFilterSet, propertyFilters, new ArrayList<String>());

            filter.add(nodeFilterSet, propertyFilterSet);
        }

        return filter;
    }

    public static String[] getPaths(MetaInf metaInf) {
        if (metaInf == null) {
            return null;
        }

        WorkspaceFilter filter = metaInf.getFilter();
        if (filter == null) {
            filter = new DefaultWorkspaceFilter();
        }
        List<PathFilterSet> filterSets = filter.getFilterSets();
        String[] paths = new String[filterSets.size()];
        for (int i = 0; i < paths.length; i++) {
            paths[i] = filterSets.get(i).getRoot();
        }

        return paths;
    }

    private static void initFilterSet(PathFilterSet filterSet, NavigableMap<String, List<String>> globalFilters, List<String> patterns) {

        // add the most specific filter rules
        String root = filterSet.getRoot();
        for (String key : globalFilters.descendingKeySet()) {
            if (root.startsWith(key)) {
                patterns.addAll(globalFilters.get(key));
                break;
            }
        }

        for (String pattern : patterns) {
            PathFilterSet.Entry<DefaultPathFilter> entry = extractPathPattern(pattern);

            if (entry.isInclude()) {
                filterSet.addInclude(entry.getFilter());
            } else {
                filterSet.addExclude(entry.getFilter());
            }
        }
    }


    public static ExportOptions getExportOptions(WorkspaceFilter filter, String[] packageRoots,
                                                 String packageGroup,
                                                 String packageName,
                                                 String packageVersion,
                                                 boolean useBinaryReferences,
                                                 Map<String, String> exportPathMapping) {
        DefaultMetaInf inf = new DefaultMetaInf();
        ExportOptions opts = new ExportOptions();
        inf.setFilter(filter);

        Properties props = new Properties();
        props.setProperty(VaultPackage.NAME_GROUP, packageGroup);
        props.setProperty(VaultPackage.NAME_NAME, packageName);
        props.setProperty(VaultPackage.NAME_VERSION, packageVersion);
        props.setProperty(PackageProperties.NAME_USE_BINARY_REFERENCES, String.valueOf(useBinaryReferences));

        if (exportPathMapping != null && !exportPathMapping.isEmpty()) {
            StringBuilder builder = new StringBuilder();

            for (Entry<String, String> entry : exportPathMapping.entrySet()) {
                if (builder.length() > 0) {
                    builder.append(MAPPING_DELIMITER);
                }

                builder.append(entry.getKey())
                       .append(MAPPING_SEPARATOR)
                       .append(entry.getValue());
            }

            props.setProperty(PATH_MAPPING_PROPERTY, builder.toString());
        }

        inf.setProperties(props);

        opts.setMetaInf(inf);

        String root = getPackageRoot(filter.getFilterSets(), packageRoots);
        opts.setRootPath(root);
        opts.setMountPath(root);

        // Set the zlib compression level to "best speed"
        // This level enables the FileVault improvement
        // covered by JCRVLT-163.
        opts.setCompressionLevel(Deflater.BEST_SPEED);

        return opts;
    }


    /**
     * Picks a package root that dominates all filter sets. If there is none then "/" is returned.
     */
    private static String getPackageRoot(List<PathFilterSet> filterSets, String[] packageRoots) {

        String packageRoot = null;

        if (packageRoots != null && packageRoots.length > 0) {
            for (String currentRoot : packageRoots) {
                boolean filtersHaveCommonRoot = true;

                for (PathFilterSet filterSet : filterSets) {
                    String filterSetRoot = filterSet.getRoot();

                    if (!filterSetRoot.startsWith(currentRoot)) {
                        filtersHaveCommonRoot = false;
                    }
                }

                if (filtersHaveCommonRoot) {
                    packageRoot = currentRoot;
                    break;
                }
            }
        }

        if (packageRoot == null || !packageRoot.startsWith("/")) {
            packageRoot = "/";
        }

        return packageRoot;
    }

    public static ImportOptions getImportOptions(AccessControlHandling aclHandling, ImportMode importMode, int autosaveThreshold) {
        ImportOptions opts = new ImportOptions();
        if (aclHandling != null) {
            opts.setAccessControlHandling(aclHandling);
        } else {
            // default to overwrite
            opts.setAccessControlHandling(AccessControlHandling.OVERWRITE);
        }
        if (importMode != null) {
            opts.setImportMode(importMode);
        } else {
            // default to update
            opts.setImportMode(ImportMode.UPDATE);
        }

        opts.setPatchKeepInRepo(false);

        if (autosaveThreshold >= 0) {
            opts.setAutoSaveThreshold(autosaveThreshold);
        }

        opts.setStrict(true);

        return opts;
    }

    public static VaultPackage createPackage(PackageManager packageManager, Session session, ExportOptions options, File tempFolder) throws IOException, RepositoryException {
        File file = File.createTempFile("distr-vault-create-" + System.nanoTime(), ".zip", tempFolder);

        try {
            return packageManager.assemble(session, options, file);
        } catch (RepositoryException e) {
            FileUtils.deleteQuietly(file);
            throw e;
        }
    }

    public static VaultPackage readPackage(PackageManager packageManager, InputStream stream, File tempFolder) throws IOException {
        File file = File.createTempFile("distr-vault-read-" + System.nanoTime(), ".zip", tempFolder);
        OutputStream out = FileUtils.openOutputStream(file);
        try {
            IOUtils.copy(stream, out);
            return packageManager.open(file);
        } catch (IOException e) {
            FileUtils.deleteQuietly(file);
            throw e;
        } finally {
            IOUtils.closeQuietly(stream);
            IOUtils.closeQuietly(out);
        }
    }

    public static void deletePackage(VaultPackage vaultPackage) {
        if (vaultPackage == null) {
            return;
        }

        File file = vaultPackage.getFile();
        vaultPackage.close();

        FileUtils.deleteQuietly(file);
    }

    public static void deletePackage(JcrPackage jcrPackage) {
        if (jcrPackage == null) {
            return;
        }

        Node node = jcrPackage.getNode();
        jcrPackage.close();

        try {
            if (node != null) {
                node.remove();
            }
        } catch (RepositoryException e) {
            // do nothing
        }
    }

    public static File getTempFolder(String tempFolderPath) {
        File directory;
        try {
            directory = new File(tempFolderPath);
            if (!directory.exists() || !directory.isDirectory()) {
                directory = null;
            }
        } catch (Throwable e) {
            directory = null;
        }

        return directory;
    }

    public static String findParent(String path, String nodeName) {
        path = path.endsWith("/") ? path : path + "/";

        nodeName = "/" + nodeName + "/";

        int idx = path.indexOf(nodeName);

        if (idx < 0) {
            return null;
        }

        return path.substring(0, idx);
    }

    public static String appendMatchAll(String path) {
        path = path.endsWith("/") ? path : path + "/";
        path = path + ".*";
        return path;
    }

    public static TreeMap<String, List<String>> parseFilters(String[] filters) {

        TreeMap<String, List<String>> result = new TreeMap<String, List<String>>();

        if (filters == null || filters.length == 0) {
            return result;
        }

        for (String filter : filters) {
            String[] filterParts = filter.split("\\|");
            if (filterParts.length > 1) {
                String path = SettingsUtils.removeEmptyEntry(filterParts[0]);
                if (path == null) {
                    continue;
                }

                List<String> filterSet = result.get(path);
                if (filterSet == null) {
                    filterSet = new ArrayList<String>();
                }

                for (int i = 1; i < filterParts.length; i++) {
                    String filterPart = SettingsUtils.removeEmptyEntry(filterParts[i]);
                    if (filterPart == null) {
                        continue;
                    }

                    filterSet.add(filterPart);
                }

                result.put(path, filterSet);

            }
        }

        return result;
    }

    public static DistributionRequest sanitizeRequest(DistributionRequest request) {

        DistributionRequestType requestType = request.getRequestType();

        if (!DistributionRequestType.ADD.equals(requestType) && !DistributionRequestType.DELETE.equals(requestType)) {
            return request;
        }

        Set<String> deepPaths = new HashSet<String>();
        List<String> paths = new ArrayList<String>();
        Map<String, String[]> filters = new HashMap<String, String[]>();

        for (String path : request.getPaths()) {
            if (VltUtils.findParent(path, "rep:policy") != null) {
                if (DistributionRequestType.DELETE.equals(requestType)) {
                    // vlt cannot properly install delete of rep:policy subnodes
                    throw new IllegalArgumentException("cannot distribute DELETE node " + path);
                } else if (DistributionRequestType.ADD.equals(requestType)) {
                    String newPath = VltUtils.findParent(path, "rep:policy") + "/rep:policy";
                    paths.add(newPath);
                    deepPaths.add(newPath);
                    log.debug("changed distribution path {} to deep path {}", path, newPath);
                }
            } else if (request.isDeep(path)) {
                paths.add(path);
                deepPaths.add(path);
            } else {
                paths.add(path);
            }

            filters.put(path, request.getFilters(path));
        }

        return new SimpleDistributionRequest(requestType, paths.toArray(new String[paths.size()]), deepPaths, filters);
    }

    private static PathFilterSet.Entry<DefaultPathFilter> extractPathPattern(String pattern) {
        PathFilterSet.Entry<DefaultPathFilter> result;
        if (pattern.startsWith("+")) {
            result = new PathFilterSet.Entry<DefaultPathFilter>(new DefaultPathFilter(pattern.substring(1)), true);
        } else if (pattern.startsWith("-")) {
            result = new PathFilterSet.Entry<DefaultPathFilter>(new DefaultPathFilter(pattern.substring(1)), false);
        } else {
            result = new PathFilterSet.Entry<DefaultPathFilter>(new DefaultPathFilter(pattern), true);
        }

        return result;
    }
}
