/*
 * Copyright 2016-present Open Networking Laboratory
 *
 * 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.onlab.osgiwrap;

import aQute.bnd.header.Attrs;
import aQute.bnd.header.Parameters;
import aQute.bnd.osgi.Analyzer;
import aQute.bnd.osgi.Builder;
import aQute.bnd.osgi.FileResource;
import aQute.bnd.osgi.Jar;
import aQute.bnd.osgi.Resource;
import com.google.common.base.Joiner;
import com.google.common.base.MoreObjects;
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 java.io.File;
import java.io.IOException;
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.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.jar.Manifest;

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

/**
 * BND-based wrapper to convert Buck JARs to OSGi-compatible JARs.
 */
public class OSGiWrapper {
    private static final String NONE = "NONE";

    private String inputJar;
    private String outputJar;
    private List<String> classpath;

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

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

    private String bundleDescription;
    private String bundleLicense;

    private String webContext;

    public static void main(String[] args) {
        if (args.length < 11) {
            System.err.println("Not enough args");
            System.exit(1);
        }

        String jar = args[0];
        String output = args[1];
        String cp = args[2];
        String name = args[3];
        String group = args[4];
        String version = args[5];
        String license = args[6];
        String importPackages = args[7];
        String exportPackages = args[8];
        String includeResources = args[9];
        String webContext = args[10];
        String desc = Joiner.on(' ').join(Arrays.copyOfRange(args, 11, args.length));

        OSGiWrapper wrapper = new OSGiWrapper(jar, output, cp,
                                              name, group,
                                              version, license,
                                              importPackages, exportPackages,
                                              includeResources,
                                              webContext, desc);
        wrapper.log(wrapper + "\n");
        if (!wrapper.execute()) {
            System.err.printf("Error generating %s\n", name);
            System.exit(2);
        }
    }


    public OSGiWrapper(String inputJar,
                       String outputJar,
                       String classpath,
                       String bundleName,
                       String groupId,
                       String bundleVersion,
                       String bundleLicense,
                       String importPackages,
                       String exportPackages,
                       String includeResources,
                       String webContext,
                       String bundleDescription) {
        this.inputJar = inputJar;
        this.classpath = Lists.newArrayList(classpath.split(":"));
        if (!this.classpath.contains(inputJar)) {
            this.classpath.add(0, inputJar);
        }
        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.exportPackages = exportPackages;
        if (!Objects.equals(includeResources, NONE)) {
            this.includeResources = includeResources;
        }

        this.webContext = webContext;
    }

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

        analyzer.setProperty(Analyzer.BUNDLE_DESCRIPTION, bundleDescription);
        analyzer.setProperty(Analyzer.BUNDLE_LICENSE, bundleLicense);

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

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

        // 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
        if (includeResources != null) {
            analyzer.setProperty(Analyzer.INCLUDE_RESOURCE, includeResources);
        }

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

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

            Jar jar = new Jar(new File(inputJar));  // 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);

//            analyzer.setProperty("DESTDIR");
//            analyzer.setBase();

            // ------------- let's begin... -------------------------

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

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

            if (includeResources != null) {
                doIncludeResources(analyzer);
            }

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

            // Calculate the manifest
            Manifest manifest = analyzer.calcManifest();
            //OutputStream s = new FileOutputStream("/tmp/foo2.txt");
            //manifest.write(s);
            //s.close();

            if (analyzer.isOk()) {
                analyzer.getJar().setManifest(manifest);
                if (analyzer.save(new File(outputJar), 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 boolean isWab() {
        return !Objects.equals(webContext, NONE);
    }

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

        log("wab %s", wab);
        analyzer.setBundleClasspath("WEB-INF/classes," +
                                    analyzer.getProperty(analyzer.BUNDLE_CLASSPATH));

        Set<String> paths = new HashSet<String>(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 sourceRootPath = Paths.get(sourceRoot);
        // 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 = sourceRootPath.relativize(file);
                String destination = destinationRoot != null ?
                        destinationRoot + "/" + relativePath.toString() : //TODO
                        relativePath.toString();

                addFileToJar(jar, destination, file.toAbsolutePath().toString());
                return FileVisitResult.CONTINUE;
            }
        };
        File dir = new File(sourceRoot);
        if (dir.isFile()) {
            addFileToJar(jar, destinationRoot, dir.getAbsolutePath());
        } else if (dir.isDirectory()) {
            walkFileTree(sourceRootPath, visitor);
        } else {
            warn("Skipping resource in bundle %s: %s (File Not Found)\n",
                 bundleSymbolicName, sourceRoot);
        }
    }

    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) {
        System.err.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();

    }
}
