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

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;

import org.apache.sling.feature.Artifact;
import org.apache.sling.feature.ArtifactId;
import org.apache.sling.feature.Configuration;
import org.apache.sling.feature.io.IOUtils;
import org.apache.sling.feature.scanner.BundleDescriptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Scan the contents of a content package.
 */
public class ContentPackageScanner {

    private static final String FILE_PACKAGE_PROPS = "META-INF/vault/properties.xml";

    private static final String FILE_MANIFEST = "META-INF/MANIFEST.MF";

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private final byte[] buffer = new byte[65536];

    enum FileType {
        BUNDLE,
        CONFIG,
        PACKAGE,
    }

    private static final List<String> CFG_EXTENSIONS = Arrays.asList(".config", ".cfg", ".cfg.json", ".xml");

    /**
     * Scan the content package for embedded artifacts
     * @param artifact The content package
     * @param url The url to the binary
     * @return A set of artifacts
     * @throws IOException If processing fails
     */
    public Set<ContentPackageDescriptorImpl> scan(final Artifact artifact, final URL url) throws IOException {
        final Set<ContentPackageDescriptorImpl> contentPackages = new HashSet<>();
        if (url != null) {
            final String path = url.getPath();
            final int lastDotInUrl = path.lastIndexOf(".");
            final String name = path.substring(path.lastIndexOf("/") + 1, lastDotInUrl);
             extractContentPackage(null, null, artifact, name, url, contentPackages);
        }

        return contentPackages;
    }

    /**
     * Detect the file type, bundle, configuration or embedded package from the content path
     * @param contentPath The content path
     * @return The detected file type or {@code null}
     */
    FileType detectContentFileType(final String contentPath) {
        FileType fileType = null;

        // check for install folders in libs or apps
        if (contentPath.startsWith("/libs/") || contentPath.startsWith("/apps/")) {

            // check if this is an install folder (I)
            // install folders are either named:
            // "install" or
            // "install.{runmode}"
            boolean isInstall = contentPath.indexOf("/install/") != -1;
            if (!isInstall) {
                final int pos = contentPath.indexOf("/install.");
                if (pos != -1) {
                    final int endSlashPos = contentPath.indexOf('/', pos + 1);
                    if (endSlashPos != -1) {
                        isInstall = true;
                    }
                }
            }
            if (!isInstall) {
                // check if this is an install folder (II)
                // config folders are either named:
                // "config" or
                // "config.{runmode}"
                isInstall = contentPath.indexOf("/config/") != -1;
                if (!isInstall) {
                    final int pos = contentPath.indexOf("/config.");
                    if (pos != -1) {
                        final int endSlashPos = contentPath.indexOf('/', pos + 1);
                        if (endSlashPos != -1) {
                            isInstall = true;
                        }
                    }
                }
            }

            if (isInstall) {

                if (contentPath.endsWith(".jar")) {
                    fileType = FileType.BUNDLE;

                } else if (contentPath.endsWith(".zip")) {
                    fileType = FileType.PACKAGE;

                } else {
                    for(final String ext : CFG_EXTENSIONS) {
                        if ( contentPath.endsWith(ext) ) {
                            fileType = FileType.CONFIG;
                            break;
                        }
                    }
                }
            }
        } else if ( contentPath.startsWith("/etc/packages/") && contentPath.endsWith(".zip")) {
            // embedded content package
            fileType = FileType.PACKAGE;
        }
        return fileType;
    }

    private ContentPackageDescriptorImpl extractContentPackage(final ContentPackageDescriptorImpl parentPackage,
            final String parentContentPath,
            final Artifact packageArtifact,
            final String name,
            final URL archiveUrl,
            final Set<ContentPackageDescriptorImpl> infos)
    throws IOException {
        logger.debug("Analyzing Content Package {}", archiveUrl);

        final File tempDir = Files.createTempDirectory(null).toFile();
        try {
            final File toDir = new File(tempDir, archiveUrl.getPath().substring(archiveUrl.getPath().lastIndexOf("/") + 1));
            toDir.mkdirs();

            Manifest manifest = null;
            final List<File> toProcess = new ArrayList<>();
            final List<String> contentPaths = new ArrayList<>();
            final List<BundleDescriptor> bundles = new ArrayList<>();
            final List<Configuration> configs = new ArrayList<>();
            final Properties packageProps = new Properties();

            try (final JarFile zipFile = IOUtils.getJarFileFromURL(archiveUrl, true, null)) {
                Enumeration<? extends ZipEntry> entries = zipFile.entries();
                while (entries.hasMoreElements()) {
                    final ZipEntry entry = entries.nextElement();
                    final String entryName = entry.getName();

                    // skip dirs
                    if ( entryName.endsWith("/") ) {
                        continue;
                    }

                    logger.debug("Content package entry {}", entryName);

                    if ( entryName.startsWith("jcr_root/") ) {
                        final String contentPath = entryName.substring(8);
                        contentPaths.add(contentPath);

                        final FileType fileType = detectContentFileType(contentPath);
                        if (fileType != null) {
                            logger.debug("- extracting : {}", contentPath);
                            final File newFile = new File(toDir, entryName.replace('/', File.separatorChar));
                            newFile.getParentFile().mkdirs();

                            try (
                                    final FileOutputStream fos = new FileOutputStream(newFile);
                                    final InputStream zis = zipFile.getInputStream(entry);
                            ) {
                                int len;
                                while ((len = zis.read(buffer)) > -1) {
                                    fos.write(buffer, 0, len);
                                }
                            }

                            if (fileType == FileType.BUNDLE) {
                                int startLevel = 20;
                                final int lastSlash = contentPath.lastIndexOf('/');
                                final int nextSlash = contentPath.lastIndexOf('/', lastSlash - 1);
                                final String part = contentPath.substring(nextSlash + 1, lastSlash);
                                try {
                                    startLevel = Integer.valueOf(part);
                                } catch (final NumberFormatException ignore) {
                                    // ignore
                                }

                                final Artifact bundle = new Artifact(extractArtifactId(packageArtifact.getId(), newFile));
                                bundle.setStartOrder(startLevel);
                                final BundleDescriptor info = new BundleDescriptorImpl(bundle, newFile.toURI().toURL());
                                bundle.getMetadata().put(ContentPackageDescriptorImpl.METADATA_PACKAGE,
                                        packageArtifact.getId().toMvnId());
                                bundle.getMetadata().put(ContentPackageDescriptorImpl.METADATA_PATH, contentPath);

                                bundles.add(info);

                            } else if (fileType == FileType.CONFIG) {

                                final Configuration configEntry = this.processConfiguration(newFile, packageArtifact.getId(), contentPath);
                                if (configEntry != null) {
                                    configs.add(configEntry);
                                }

                            } else if (fileType == FileType.PACKAGE) {
                                toProcess.add(newFile);
                            }
                        }
                    } else if ( FILE_MANIFEST.equals(entry.getName()) ) {
                        try ( final InputStream zis = zipFile.getInputStream(entry)) {
                            manifest = new Manifest(zis);
                        } catch ( final IOException ignore ) {
                            logger.warn("Failure reading manifest from {} : {}", packageArtifact.getId(), ignore.getMessage());
                        }
                    } else if ( FILE_PACKAGE_PROPS.equals(entry.getName()) ) {
                        try ( final InputStream zis = zipFile.getInputStream(entry)) {
                            packageProps.loadFromXML(zis);
                        }
                    }
                }

                final ContentPackageDescriptorImpl desc = new ContentPackageDescriptorImpl(name, packageArtifact, archiveUrl, manifest,
                    bundles, contentPaths, configs, packageProps);
                if ( parentPackage != null ) {
                    desc.setParentContentPackageInfo(parentPackage, parentContentPath);
                }

                for (final File f : toProcess) {
                    final int lastDot = f.getName().lastIndexOf(".");
                    final String subName = f.getName().substring(0, lastDot);
                    final String contentPath = f.getAbsolutePath().substring(toDir.getAbsolutePath().length()).replace(File.separatorChar, '/');

                    // create synthetic artifact with a synthetic id containing the file name
                    final Artifact subArtifact = new Artifact(packageArtifact.getId().changeClassifier(subName));

                    extractContentPackage(desc, contentPath, subArtifact, subName, f.toURI().toURL(), infos);
                }

                infos.add(desc);
                desc.lock();
                return desc;
            }
        } finally {
            deleteOnExitRecursive(tempDir);
        }
    }

    private void deleteOnExitRecursive(File file) {
        file.deleteOnExit();
        if (file.isDirectory()) {
            File[] childs = file.listFiles();
            if (childs != null) {
                for (File child : childs) {
                    deleteOnExitRecursive(child);
                }
            }
        }
    }

    final List<Properties> getInitialCandidates(final File bundleFile)  throws IOException{
        logger.debug("Extracting Bundle {}", bundleFile.getName());

        final List<Properties> candidates = new ArrayList<>();
        try (final JarFile zipFile = new JarFile(bundleFile)) {
            Enumeration<? extends ZipEntry> entries = zipFile.entries();

            while ( entries.hasMoreElements() ) {
                final ZipEntry entry = entries.nextElement();

                final String entryName = entry.getName();
                if ( !entryName.endsWith("/") && entryName.startsWith("META-INF/maven/") && entryName.endsWith("/pom.properties")) {
                    logger.debug("- extracting : {}", entryName);

                    final Properties props = new Properties();
                    try (final InputStream zis = zipFile.getInputStream(entry)) {
                        props.load(zis);
                    }
                    candidates.add(props);
                }
            }
        }
        return candidates;
    }

    private String adjustVersion(final String version) {
        final String parts[] = version.split("\\.");
        if ( parts.length == 4 ) {
            final int lastDot = version.lastIndexOf('.');
            return version.substring(0, lastDot) + '-' + version.substring(lastDot + 1);
        }
        return version;
    }

    private ArtifactId adjustClassifier(ArtifactId id, final String bundleFileName) {
        // check for classifier
        final int versionStart = bundleFileName.indexOf(id.getVersion());
        if ( versionStart != -1 ) {
            // capture classifier
            final int versionEnd = versionStart + id.getVersion().length();
            if ( bundleFileName.length() > versionEnd && bundleFileName.charAt(versionEnd) == '-') {
                id = id.changeClassifier(bundleFileName.substring(versionEnd + 1, bundleFileName.lastIndexOf('.')));
            }
        }
        return id;
    }

    private ArtifactId extractArtifactId(final ArtifactId packageArtifactId, final File bundleFile)
    throws IOException {
        final List<Properties> candidates = this.getInitialCandidates(bundleFile);
        return extractArtifactId(candidates, bundleFile.getName(), packageArtifactId);
    }

    private List<ArtifactId> getArtifactIds(final List<Properties> candidates) {
        final List<ArtifactId> idCandidates = new ArrayList<>();
        for(final Properties props : candidates) {
            final String version = props.getProperty("version");
            final String groupId = props.getProperty("groupId");
            final String artifactId = props.getProperty("artifactId");

            if ( version != null && groupId != null && artifactId != null ) {
                idCandidates.add(new ArtifactId(groupId, artifactId, adjustVersion(version), null, null));
            }
        }
        return idCandidates;
    }

    private List<ArtifactId> filterCandidatesByVersion(final List<ArtifactId> ids, final String bundleFileName) {
        final List<ArtifactId> idCandidates = new ArrayList<>();
        for(final ArtifactId id : ids) {
            final int versionStart = bundleFileName.indexOf(id.getVersion());
            if ( versionStart != -1 ) {
                idCandidates.add(id);
            }
        }
        return idCandidates;
    }

    ArtifactId extractArtifactId(final List<Properties> candidates, final String bundleFileName, final ArtifactId packageArtifactId)
    throws IOException {
        logger.debug("Properties candidates for {} : {}", bundleFileName, candidates);

        final List<ArtifactId> idCandidates = getArtifactIds(candidates);
        logger.debug("Artifact candidates for {} : {}", bundleFileName, candidates);

        // single candidate? return
        if ( idCandidates.size() == 1 ) {
            final ArtifactId result = adjustClassifier(idCandidates.get(0), bundleFileName);
            logger.debug("Found single candidate : {}", result);
            return result;
        }

        // more than one candidate, find matching version
        final List<ArtifactId> versionIds = filterCandidatesByVersion(idCandidates, bundleFileName);
        if ( versionIds.size() == 1 ) {
            final ArtifactId result = adjustClassifier(versionIds.get(0), bundleFileName);
            logger.debug("Found single candidate matching version : {}", result);
            return result;
        }
        // check parent group id
        for(final ArtifactId id : versionIds.isEmpty() ? idCandidates : versionIds) {
            if ( id.getGroupId().equals(packageArtifactId.getGroupId()) ) {
                final ArtifactId result = adjustClassifier(id, bundleFileName);
                logger.debug("Found candidate with parent group id {} : {}",packageArtifactId.getGroupId(), result);
                return result;
            }
        }
        // randomly pick one
        if ( idCandidates.size() > 0 ) {
            final ArtifactId result = adjustClassifier(idCandidates.get(0), bundleFileName);
            logger.debug("Picking random candidate : {}", result);
            return result;
        }

        throw new IOException(bundleFileName + " has no maven coordinates!");
    }

    Configuration processConfiguration(final File configFile,
            final ArtifactId packageArtifactId,
            final String contentPath)
    throws IOException {

        boolean isConfig = true;
        if ( contentPath.endsWith(".xml") ) {
            final String contents = Files.readAllLines(configFile.toPath()).toString();
            if ( contents.indexOf("jcr:primaryType=\"sling:OsgiConfig\"") == -1 ) {
                isConfig = false;
            }
        }

        if ( isConfig ) {
            final String id;
            if ( contentPath.endsWith("/.content.xml") ) {
                final int lastSlash = contentPath.lastIndexOf('/');
                final int previousSlash = contentPath.lastIndexOf('/', lastSlash - 1);
                id = contentPath.substring(previousSlash + 1, lastSlash);
            } else {
                String name = contentPath;
                final int lastSlash = contentPath.lastIndexOf('/');
                for(final String ext : CFG_EXTENSIONS) {
                    if ( name.endsWith(ext) ) {
                        name = name.substring(lastSlash + 1, name.length() - ext.length());
                    }
                }
                id = name;
            }

            final String pid;
            final int slashPos = id.indexOf('-');
            if ( slashPos == -1 ) {
                pid = id;
            } else {
                pid = id.substring(0, slashPos) + '~' + id.substring(slashPos + 1);
            }

            final Configuration cfg = new Configuration(pid);
            cfg.getProperties().put(Configuration.PROP_PREFIX + ContentPackageDescriptorImpl.METADATA_PATH, contentPath);
            cfg.getProperties().put(Configuration.PROP_PREFIX + ContentPackageDescriptorImpl.METADATA_PACKAGE,
                    packageArtifactId.toMvnId());

            return cfg;
        }

        return null;
    }
}
