/*
 * 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
 *
 *   https://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.
 */

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry;

import org.apache.bcel.Const;
import org.apache.bcel.classfile.ClassParser;
import org.apache.bcel.classfile.Constant;
import org.apache.bcel.classfile.ConstantClass;
import org.apache.bcel.classfile.ConstantPool;
import org.apache.bcel.classfile.ConstantUtf8;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Utility;
import org.apache.bcel.util.ClassPath;

/**
 * Package the client. Creates a jar file in the current directory that contains a minimal set of classes needed to run
 * the client.
 *
 * Use BCEL to extract class names and read/write classes
 */
public class Package {

    /**
     * The name of the resulting jar is Client.jar
     */
    static String defaultJar = "Client.jar";

    /*
     * See usage() for arguments. Create an instance and run that (just so not all members have to be static)
     */
    static void main(final String args[]) {
        final Package instance = new Package();
        try {
            instance.go(args);
        } catch (final Exception e) {
            e.printStackTrace();
            instance.usage();
        }
    }

    /**
     * We use a "default ClassPath object which uses the environments CLASSPATH
     */
    ClassPath classPath = ClassPath.SYSTEM_CLASS_PATH;

    /**
     * A map for all Classes, the ones we're going to package. Store class name against the JavaClass. From the JavaClass we
     * get the bytes to create the jar.
     */
    Map<String, JavaClass> allClasses = new TreeMap<>();

    /**
     * We start at the root classes, put them in here, then go through this list, putting dependent classes in here and from
     * there into allClasses. Store class names against class names of their dependents
     */
    TreeMap<String, String> dependents = new TreeMap<>();

    /**
     * Collect all classes that could not be found in the classpath. Store class names against class names of their
     * dependents
     */
    TreeMap<String, String> notFound = new TreeMap<>();

    /**
     * See wheather we print the classes that were not found (default = false)
     */
    boolean showNotFound = false;

    /**
     * Remember wheather to print allClasses at the end (default = false)
     */
    boolean printClasses = false;

    /**
     * Wheather we log classes during processing (default = false)
     */
    boolean log = false;

    /**
     * add given class to dependents (from is where its dependent from) some fiddeling to be done because of array class
     * notation
     */
    void addClassString(final String clas, final String from) throws IOException {
        if (log) {
            System.out.println("processing: " + clas + " referenced by " + from);
        }

        // must check if it's an arrary (start with "[")
        if (clas.startsWith("[")) {
            if (clas.length() == 2) {
                // it's an array of built in type, ignore
                return;
            }
            if ('L' == clas.charAt(1)) {
                // it's an array of objects, the class name is between [L and ;
                // like [Ljava/lang/Object;
                addClassString(clas.substring(2, clas.length() - 1), from);
                return;
            }
            if ('[' == clas.charAt(1)) {
                // it's an array of arrays, call recursive
                addClassString(clas.substring(1), from);
                return;
            }
            throw new IllegalArgumentException("Can't recognize class name =" + clas);
        }

        if (!clas.startsWith("java/") && allClasses.get(clas) == null) {
            dependents.put(clas, from);
            // System.out.println(" yes" );
        } else {
            // System.out.println(" no" );
        }
    }

    /**
     * Add this class to allClasses. Then go through all its dependents and add them to the dependents list if they are not
     * in allClasses
     */
    void addDependents(final JavaClass clazz) throws IOException {
        final String name = Utility.packageToPath(clazz.getClassName());
        allClasses.put(name, clazz);
        final ConstantPool pool = clazz.getConstantPool();
        for (int i = 1; i < pool.getLength(); i++) {
            final Constant cons = pool.getConstant(i);
            // System.out.println("("+i+") " + cons );
            if (cons != null && cons.getTag() == Const.CONSTANT_Class) {
                final int idx = ((ConstantClass) pool.getConstant(i)).getNameIndex();
                final String clas = ((ConstantUtf8) pool.getConstant(idx)).getBytes();
                addClassString(clas, name);
            }
        }
    }

    /**
     * the main of this class
     */
    void go(final String[] args) throws IOException {
        JavaClass clazz;
        // sort the options
        for (final String arg : args) {
            if (arg.startsWith("-e")) {
                showNotFound = true;
                continue;
            }
            if (arg.startsWith("-s")) {
                printClasses = true;
                continue;
            }
            if (arg.startsWith("-l")) {
                log = true;
                continue;
            }
            String clName = arg;
            if (clName.endsWith(JavaClass.EXTENSION)) {
                clName = clName.substring(0, clName.length() - JavaClass.EXTENSION.length());
            }
            clName = Utility.packageToPath(clName);
            try (InputStream inputStream = classPath.getInputStream(clName)) {
                clazz = new ClassParser(inputStream, clName).parse();
            }
            // here we create the root set of classes to process
            addDependents(clazz);
            System.out.println("Packaging for class: " + clName);
        }

        if (dependents.isEmpty()) {
            usage();
            return;
        }

        System.out.println("Creating jar file: " + defaultJar);

        // starting processing: Grab from the dependents list and add back to it
        // and the allClasses list. see addDependents
        while (!dependents.isEmpty()) {
            final String name = dependents.firstKey();
            final String from = dependents.remove(name);
            if (allClasses.get(name) == null) {
                try (InputStream inputStream = classPath.getInputStream(name)) {
                    clazz = new ClassParser(inputStream, name).parse();
                    addDependents(clazz);
                } catch (final IOException e) {
                    // System.err.println("Error, class not found " + name );
                    notFound.put(name, from);
                }
            }
        }

        if (printClasses) { // if wanted show all classes
            printAllClasses();
        }

        // create the jar
        try (JarOutputStream jarFile = new JarOutputStream(new FileOutputStream(defaultJar))) {
            jarFile.setLevel(5); // use compression
            int written = 0;
            for (final Entry<String, JavaClass> entry : allClasses.entrySet()) { // add entries for every class
                final JavaClass claz = allClasses.get(entry.getKey());
                final ZipEntry zipEntry = new ZipEntry(entry.getValue() + JavaClass.EXTENSION);
                final byte[] bytes = claz.getBytes();
                final int length = bytes.length;
                jarFile.putNextEntry(zipEntry);
                jarFile.write(bytes, 0, length);
                written += length; // for logging
            }
            System.err.println("The jar file contains " + allClasses.size() + " classes and contains " + written + " bytes");
        }

        if (!notFound.isEmpty()) {
            System.err.println(notFound.size() + " classes could not be found");
            if (showNotFound) { // if wanted show the actual classes that we not found
                while (!notFound.isEmpty()) {
                    final String name = notFound.firstKey();
                    System.err.println(name + " (" + notFound.remove(name) + ")");
                }
            } else {
                System.err.println("Use '-e' option to view classes that were not found");
            }
        }
    }

    /**
     * Print all classes that were packaged. Sort alphabetically for better overview. Enabled by -s option
     */
    void printAllClasses() {
        final List<String> names = new ArrayList<>(allClasses.keySet());
        Collections.sort(names);
        names.forEach(System.err::println);
    }

    public void usage() {
        System.out.println(" This program packages classes and all their dependents");
        System.out.println(" into one jar. Give all starting classes (your main)");
        System.out.println(" on the command line. Use / as separator, the .class is");
        System.out.println(" optional. We use the environments CLASSPATH to resolve");
        System.out.println(" classes. Anything but java.* packages are packaged.");
        System.out.println(" If you use Class.forName (or similar), be sure to");
        System.out.println(" include the classes that you load dynamically on the");
        System.out.println(" command line.\n");
        System.out.println(" These options are recognized:");
        System.out.println(" -e -error  Show errors, meaning classes that could not ");
        System.out.println("   resolved + the classes that referenced them.");
        System.out.println(" -l -log  Show classes as they are processed. This will");
        System.out.println("   include doubles, java classes and is difficult to");
        System.out.println("   read. I use it as a sort of progress monitor");
        System.out.println(" -s -show  Prints all the classes that were packaged");
        System.out.println("   in alphabetical order, which is ordered by package");
        System.out.println("   for the most part.");
    }
}
