/*
 * Copyright 2016-present Open Networking Foundation
 *
 * Licensed 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.onosproject.onosjar;

import aQute.bnd.header.Attrs;
import aQute.bnd.header.Parameters;
import aQute.bnd.osgi.Analyzer;
import aQute.bnd.osgi.Builder;
import aQute.bnd.osgi.Constants;
import aQute.bnd.osgi.Descriptors;
import aQute.bnd.osgi.FileResource;
import aQute.bnd.osgi.Jar;
import aQute.bnd.osgi.Packages;
import aQute.bnd.osgi.Processor;
import aQute.bnd.osgi.Resource;
import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.step.Step;
import com.facebook.buck.step.StepExecutionResult;
import com.google.common.base.MoreObjects;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.felix.scrplugin.bnd.SCRDescriptorBndPlugin;
import org.codehaus.plexus.util.DirectoryScanner;

import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.jar.Manifest;
import java.util.stream.Collectors;

import static java.nio.file.Files.walkFileTree;

/**
 * BND-based wrapper to convert Buck JARs to OSGi-compatible JARs.
 */
public class OSGiWrapper implements Step {

    private static final String EMBED_DEPENDENCY = "Embed-Dependency";
    private static final String EMBEDDED_ARTIFACTS = "Embedded-Artifacts";

    private Path inputJar;
    private Path outputJar;
    private Path sourcesDir;
    private Path classesDir;
    private List<String> classpath;

    private String bundleName;
    private String groupId;
    private String bundleSymbolicName;
    private String bundleVersion;

    private String importPackages;
    private String privatePackages;
    private String dynamicimportPackages;
    private String embeddedDependencies;

    private String exportPackages;
    private String includeResources;
    private Set<String> includedResources = Sets.newHashSet();

    private String bundleDescription;
    private String bundleLicense;

    private String bundleClasspath;

    private String webContext;

    private PrintStream stderr = System.err;

    public OSGiWrapper(Path inputJar,
                       Path outputJar,
                       Path sourcesDir,
                       Path classesDir,
                       ImmutableSortedSet<Path> classpath,
                       String bundleName,
                       String groupId,
                       String bundleVersion,
                       String bundleLicense,
                       String importPackages,
                       String exportPackages,
                       String includeResources,
                       String webContext,
                       String dynamicimportPackages,
                       String embeddedDependencies,
                       String bundleDescription,
                       String privatePackages,
                       String bundleClasspath) {
        this.inputJar = inputJar;
        this.sourcesDir = sourcesDir;
        this.classesDir = classesDir;
        this.classpath = Lists.newArrayList(
                classpath.stream().map(Path::toString).collect(Collectors.toList()));
        if (!this.classpath.contains(inputJar.toString())) {
            this.classpath.add(0, inputJar.toString());
        }
        this.outputJar = outputJar;

        this.bundleName = bundleName;
        this.groupId = groupId;
        this.bundleSymbolicName = String.format("%s.%s", groupId, bundleName);

        this.bundleVersion = bundleVersion;
        this.bundleLicense = bundleLicense;
        this.bundleDescription = bundleDescription;

        this.importPackages = importPackages;
        this.privatePackages = privatePackages;
        this.dynamicimportPackages = dynamicimportPackages;
        this.embeddedDependencies = embeddedDependencies;
        this.exportPackages = exportPackages;
        this.includeResources = includeResources;

        this.webContext = webContext;

        this.bundleClasspath = bundleClasspath;
    }

    private void setProperties(Analyzer analyzer) {

        analyzer.setProperty(Analyzer.BUNDLE_NAME, bundleName);
        analyzer.setProperty(Analyzer.BUNDLE_SYMBOLICNAME, bundleSymbolicName);
        analyzer.setProperty(Analyzer.BUNDLE_VERSION, bundleVersion.replace('-', '.'));

        if (bundleDescription != null) {
            analyzer.setProperty(Analyzer.BUNDLE_DESCRIPTION, bundleDescription);
        }
        if (bundleLicense != null) {
            analyzer.setProperty(Analyzer.BUNDLE_LICENSE, bundleLicense);
        }

        //TODO consider using stricter version policy
        //analyzer.setProperty("-provider-policy", "${range;[===,==+)}");
        //analyzer.setProperty("-consumer-policy", "${range;[===,==+)}");

        if (privatePackages != null) {
            analyzer.setProperty(Analyzer.PRIVATE_PACKAGE, privatePackages);
        }
        analyzer.setProperty(Analyzer.REMOVEHEADERS, "Private-Package,Include-Resource");

        analyzer.setProperty(Analyzer.DYNAMICIMPORT_PACKAGE,
                             dynamicimportPackages);

        // TODO include version in export, but not in import
        analyzer.setProperty(Analyzer.EXPORT_PACKAGE, exportPackages);

        // TODO we may need INCLUDE_RESOURCE, or that might be done by Buck
        // FIXME NOTE we handle this manually below
        if (includeResources != null) {
            analyzer.setProperty(Analyzer.INCLUDE_RESOURCE, includeResources);
        }

        if (embeddedDependencies != null) {
            analyzer.setProperty(EMBED_DEPENDENCY, embeddedDependencies);
        }

        // There are no good defaults so make sure you set the Import-Package
        analyzer.setProperty(Analyzer.IMPORT_PACKAGE, importPackages);

        if (isWab()) {
            analyzer.setProperty(Analyzer.WAB, "src/main/webapp/");
            analyzer.setProperty("Web-ContextPath", webContext);
            analyzer.setProperty(Analyzer.IMPORT_PACKAGE, importPackages +
                    ",org.glassfish.jersey.servlet,org.jvnet.mimepull\n");
        }
    }

    public boolean execute() {
        Builder analyzer = new Builder();
        try {

            Jar jar = new Jar(inputJar.toFile());   // where our data is
            analyzer.setJar(jar);                   // give bnd the contents

            // You can provide additional class path entries to allow
            // bnd to pickup export version from the packageinfo file,
            // Version annotation, or their manifests.
            analyzer.addClasspath(classpath);

            setProperties(analyzer);

            // Analyze the target JAR first
            analyzer.analyze();

            // Scan the JAR for Felix SCR annotations and generate XML files
            Map<String, String> properties = Maps.newHashMap();
            properties.put("destdir", classesDir.toAbsolutePath().toString());
            SCRDescriptorBndPlugin scrDescriptorBndPlugin = new SCRDescriptorBndPlugin();
            scrDescriptorBndPlugin.setProperties(properties);
            scrDescriptorBndPlugin.setReporter(analyzer);
            scrDescriptorBndPlugin.analyzeJar(analyzer);

            //Add local packges to jar file.
            //FIXME removing this call for now; not sure what exactly it's doing
            //addLocalPackages(new File(classesDir.toString()), analyzer);

            //add resources.
            if (includeResources != null || embeddedDependencies != null) {
                doIncludeResources(analyzer);
            }

            // Repack the JAR as a WAR
            doWabStaging(analyzer);

            // Calculate the manifest
            Manifest manifest = analyzer.calcManifest();

            //Build the jar files
            //FIXME this call conflicts with some of the above
//            analyzer.build();

            if (analyzer.isOk()) {
                //add calculated manifest file.
                analyzer.getJar().setManifest(manifest);
                if (analyzer.save(outputJar.toFile(), true)) {
                    log("Saved!\n");
                } else {
                    warn("Failed to create jar \n");
                    return false;
                }
            } else {
                warn("Analyzer Errors:\n%s\n", analyzer.getErrors());
                return false;
            }

            analyzer.close();

            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    private static void addLocalPackages(File outputDirectory, Analyzer analyzer) throws IOException {
        Packages packages = new Packages();

        if (outputDirectory != null && outputDirectory.isDirectory()) {
            // scan classes directory for potential packages
            DirectoryScanner scanner = new DirectoryScanner();
            scanner.setBasedir(outputDirectory);
            scanner.setIncludes(new String[]
                                        {"**/*.class"});

            scanner.addDefaultExcludes();
            scanner.scan();

            String[] paths = scanner.getIncludedFiles();
            for (int i = 0; i < paths.length; i++) {
                packages.put(analyzer.getPackageRef(getPackageName(paths[i])));
            }
        }

        Packages exportedPkgs = new Packages();
        Packages privatePkgs = new Packages();

        boolean noprivatePackages = "!*".equals(analyzer.getProperty(Analyzer.PRIVATE_PACKAGE));

        for (Descriptors.PackageRef pkg : packages.keySet()) {
            // mark all source packages as private by default (can be overridden by export list)
            privatePkgs.put(pkg);

            // we can't export the default package (".") and we shouldn't export internal packages
            String fqn = pkg.getFQN();
            if (noprivatePackages || !(".".equals(fqn) || fqn.contains(".internal") || fqn.contains(".impl"))) {
                exportedPkgs.put(pkg);
            }
        }

        Properties properties = analyzer.getProperties();
        String exported = properties.getProperty(Analyzer.EXPORT_PACKAGE);
        if (exported == null) {
            if (!properties.containsKey(Analyzer.EXPORT_CONTENTS)) {
                // no -exportcontents overriding the exports, so use our computed list
                for (Attrs attrs : exportedPkgs.values()) {
                    attrs.put(Constants.SPLIT_PACKAGE_DIRECTIVE, "merge-first");
                }
                properties.setProperty(Analyzer.EXPORT_PACKAGE, Processor.printClauses(exportedPkgs));
            } else {
                // leave Export-Package empty (but non-null) as we have -exportcontents
                properties.setProperty(Analyzer.EXPORT_PACKAGE, "");
            }
        }

        String internal = properties.getProperty(Analyzer.PRIVATE_PACKAGE);
        if (internal == null) {
            if (!privatePkgs.isEmpty()) {
                for (Attrs attrs : privatePkgs.values()) {
                    attrs.put(Constants.SPLIT_PACKAGE_DIRECTIVE, "merge-first");
                }
                properties.setProperty(Analyzer.PRIVATE_PACKAGE, Processor.printClauses(privatePkgs));
            } else {
                // if there are really no private packages then use "!*" as this will keep the Bnd Tool happy
                properties.setProperty(Analyzer.PRIVATE_PACKAGE, "!*");
            }
        }
    }

    private static String getPackageName(String filename) {
        int n = filename.lastIndexOf(File.separatorChar);
        return n < 0 ? "." : filename.substring(0, n).replace(File.separatorChar, '.');
    }

    private boolean isWab() {
        return webContext != null;
    }

    private void doWabStaging(Analyzer analyzer) throws Exception {
        if (!isWab()) {
            return;
        }
        String wab = analyzer.getProperty(analyzer.WAB);
        Jar dot = analyzer.getJar();

        log("wab %s", wab);

        if (bundleClasspath != null) {
            analyzer.setBundleClasspath("WEB-INF/classes," + bundleClasspath);
        }

        Set<String> paths = new HashSet<>(dot.getResources().keySet());

        for (String path : paths) {
            if (path.indexOf('/') > 0 && !Character.isUpperCase(path.charAt(0))) {
                log("wab: moving: %s", path);
                dot.rename(path, "WEB-INF/classes/" + path);
            }
        }

        Path wabRoot = Paths.get(wab);
        includeFiles(dot, null, wabRoot.toString());
    }

    /**
     * Parse the Bundle-Includes header. Files in the bundles Include header are
     * included in the jar. The source can be a directory or a file.
     *
     * @throws Exception
     */
    private void doIncludeResources(Analyzer analyzer) throws Exception {
        String includes = analyzer.getProperty(Analyzer.INCLUDE_RESOURCE);
        if (includes == null) {
            return;
        }
        Parameters clauses = analyzer.parseHeader(includes);
        Jar jar = analyzer.getJar();

        for (Map.Entry<String, Attrs> entry : clauses.entrySet()) {
            String name = entry.getKey();
            Map<String, String> extra = entry.getValue();
            // TODO consider doing something with extras

            String[] parts = name.split("\\s*=\\s*");
            String source = parts[0];
            String destination = parts[0];
            if (parts.length == 2) {
                source = parts[1];
            }

            includeFiles(jar, destination, source);
        }
    }

    private void includeFiles(Jar jar, String destinationRoot, String sourceRoot)
            throws IOException {

        Path classesBasedPath = classesDir.resolve(sourceRoot);
        Path sourceBasedPath = sourcesDir.resolve(sourceRoot);

        File classFile = classesBasedPath.toFile();
        File sourceFile = sourceBasedPath.toFile();

        if (classFile.isFile()) {
            addFileToJar(jar, destinationRoot, classesBasedPath.toAbsolutePath().toString());
        } else if (sourceFile.isFile()) {
            addFileToJar(jar, destinationRoot, sourceBasedPath.toAbsolutePath().toString());
        } else if (classFile.isDirectory()) {
            includeDirectory(jar, destinationRoot, classesBasedPath);
        } else if (sourceFile.isDirectory()) {
            includeDirectory(jar, destinationRoot, sourceBasedPath);
        } else {
            warn("Skipping resource in bundle %s: %s (File Not Found)\n",
                 bundleSymbolicName, sourceRoot);
        }
    }

    private void includeDirectory(Jar jar, String destinationRoot, Path sourceRoot)
            throws IOException {
        // iterate through sources
        // put each source on the jar
        FileVisitor<Path> visitor = new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                Path relativePath = sourceRoot.relativize(file);
                String destination = destinationRoot != null ?
                        destinationRoot + "/" + relativePath.toString() : //TODO
                        relativePath.toString();

                addFileToJar(jar, destination, file.toAbsolutePath().toString());
                return FileVisitResult.CONTINUE;
            }
        };

        walkFileTree(sourceRoot, visitor);
    }

    private boolean addFileToJar(Jar jar, String destination, String sourceAbsPath) {
        if (includedResources.contains(sourceAbsPath)) {
            log("Skipping already included resource: %s\n", sourceAbsPath);
            return false;
        }
        File file = new File(sourceAbsPath);
        if (!file.isFile()) {
            throw new RuntimeException(
                    String.format("Skipping non-existent file: %s\n", sourceAbsPath));
        }
        Resource resource = new FileResource(file);
        if (jar.getResource(destination) != null) {
            warn("Skipping duplicate resource: %s\n", destination);
            return false;
        }
        jar.putResource(destination, resource);
        includedResources.add(sourceAbsPath);
        log("Adding resource: %s\n", destination);
        return true;
    }

    private void log(String format, Object... objects) {
        //System.err.printf(format, objects);
    }

    private void warn(String format, Object... objects) {
        stderr.printf(format, objects);
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
                .add("inputJar", inputJar)
                .add("outputJar", outputJar)
                .add("classpath", classpath)
                .add("bundleName", bundleName)
                .add("groupId", groupId)
                .add("bundleSymbolicName", bundleSymbolicName)
                .add("bundleVersion", bundleVersion)
                .add("bundleDescription", bundleDescription)
                .add("bundleLicense", bundleLicense)
                .toString();
    }

    @Override
    public StepExecutionResult execute(ExecutionContext executionContext)
            throws IOException, InterruptedException {
        stderr = executionContext.getStdErr();
        boolean success = execute();
        stderr = System.err;
        return success ? StepExecutionResult.SUCCESS : StepExecutionResult.ERROR;
    }

    @Override
    public String getShortName() {
        return "osgiwrap";
    }

    @Override
    public String getDescription(ExecutionContext executionContext) {
        return "osgiwrap"; //FIXME
    }
}
