/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.mozilla.gecko.annotationProcessors;

import com.android.tools.lint.checks.ApiLookup;
import com.android.tools.lint.LintCliClient;

import org.mozilla.gecko.annotationProcessors.classloader.AnnotatableEntity;
import org.mozilla.gecko.annotationProcessors.classloader.ClassWithOptions;
import org.mozilla.gecko.annotationProcessors.classloader.IterableJarLoadingURLClassLoader;
import org.mozilla.gecko.annotationProcessors.utils.GeneratableElementIterator;
import org.mozilla.gecko.annotationProcessors.utils.Utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Properties;
import java.util.Scanner;
import java.util.Vector;
import java.net.URL;
import java.net.URLClassLoader;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class SDKProcessor {
    public static final String GENERATED_COMMENT =
            "// GENERATED CODE\n" +
            "// Generated by the Java program at /build/annotationProcessors at compile time\n" +
            "// from annotations on Java methods. To update, change the annotations on the\n" +
            "// corresponding Javamethods and rerun the build. Manually updating this file\n" +
            "// will cause your build to fail.\n" +
            "\n";

    private static ApiLookup sApiLookup;
    private static int sMaxSdkVersion;

    public static void main(String[] args) throws Exception {
        // We expect a list of jars on the commandline. If missing, whinge about it.
        if (args.length < 5) {
            System.err.println("Usage: java SDKProcessor sdkjar classlistfile outdir fileprefix max-sdk-version");
            System.exit(1);
        }

        System.out.println("Processing platform bindings...");

        String sdkJar = args[0];
        Vector classes = getClassList(args[1]);
        String outdir = args[2];
        String generatedFilePrefix = args[3];
        sMaxSdkVersion = Integer.parseInt(args[4]);

        LintCliClient lintClient = new LintCliClient();
        sApiLookup = ApiLookup.get(lintClient);

        // Start the clock!
        long s = System.currentTimeMillis();

        // Get an iterator over the classes in the jar files given...
        // Iterator<ClassWithOptions> jarClassIterator = IterableJarLoadingURLClassLoader.getIteratorOverJars(args);

        StringBuilder headerFile = new StringBuilder(GENERATED_COMMENT);
        headerFile.append(
                "#ifndef " + generatedFilePrefix + "_h__\n" +
                "#define " + generatedFilePrefix + "_h__\n" +
                "\n" +
                "#include \"mozilla/jni/Refs.h\"\n" +
                "\n" +
                "namespace mozilla {\n" +
                "namespace widget {\n" +
                "namespace sdk {\n" +
                "\n");

        StringBuilder implementationFile = new StringBuilder(GENERATED_COMMENT);
        implementationFile.append(
                "#include \"" + generatedFilePrefix + ".h\"\n" +
                "#include \"mozilla/jni/Accessors.h\"\n" +
                "\n" +
                "namespace mozilla {\n" +
                "namespace widget {\n" +
                "namespace sdk {\n" +
                "\n");

        // Used to track the calls to the various class-specific initialisation functions.
        ClassLoader loader = null;
        try {
            loader = URLClassLoader.newInstance(new URL[] { new URL("file://" + sdkJar) },
                                                SDKProcessor.class.getClassLoader());
        } catch (Exception e) {
            throw new RuntimeException(e.toString());
        }

        for (Iterator<String> i = classes.iterator(); i.hasNext(); ) {
            String className = i.next();
            System.out.println("Looking up: " + className);

            generateClass(Class.forName(className, true, loader),
                          implementationFile,
                          headerFile);
        }

        implementationFile.append(
                "} /* sdk */\n" +
                "} /* widget */\n" +
                "} /* mozilla */\n");

        headerFile.append(
                "} /* sdk */\n" +
                "} /* widget */\n" +
                "} /* mozilla */\n" +
                "#endif\n");

        writeOutputFiles(outdir, generatedFilePrefix, headerFile, implementationFile);
        long e = System.currentTimeMillis();
        System.out.println("SDK processing complete in " + (e - s) + "ms");
    }

    private static int getAPIVersion(Class<?> cls, Member m) {
        if (m instanceof Method || m instanceof Constructor) {
            return sApiLookup.getCallVersion(
                    cls.getName().replace('.', '/'),
                    Utils.getMemberName(m),
                    Utils.getSignature(m));
        } else if (m instanceof Field) {
            return sApiLookup.getFieldVersion(
                    Utils.getClassDescriptor(m.getDeclaringClass()), m.getName());
        } else {
            throw new IllegalArgumentException("expected member to be Method, Constructor, or Field");
        }
    }

    private static Member[] sortAndFilterMembers(Class<?> cls, Member[] members) {
        Arrays.sort(members, new Comparator<Member>() {
            @Override
            public int compare(Member a, Member b) {
                return a.getName().compareTo(b.getName());
            }
        });

        ArrayList<Member> list = new ArrayList<>();
        for (Member m : members) {
            // Sometimes (e.g. Bundle) has methods that moved to/from a superclass in a later SDK
            // version, so we check for both classes and see if we can find a minimum SDK version.
            int version = getAPIVersion(cls, m);
            final int version2 = getAPIVersion(m.getDeclaringClass(), m);
            if (version2 > 0 && version2 < version) {
                version = version2;
            }
            if (version > sMaxSdkVersion) {
                System.out.println("Skipping " + m.getDeclaringClass().getName() + "." + m.getName() +
                    ", version " + version + " > " + sMaxSdkVersion);
                continue;
            }

            // Sometimes (e.g. KeyEvent) a field can appear in both a class and a superclass. In
            // that case we want to filter out the version that appears in the superclass, or
            // we'll have bindings with duplicate names.
            try {
                if (m instanceof Field && !m.equals(cls.getField(m.getName()))) {
                    // m is a field in a superclass that has been hidden by
                    // a field with the same name in a subclass.
                    System.out.println("Skipping " + m.getName() +
                                       " from " + m.getDeclaringClass());
                    continue;
                }
            } catch (final NoSuchFieldException e) {
            }

            list.add(m);
        }

        return list.toArray(new Member[list.size()]);
    }

    private static void generateClass(Class<?> clazz,
                                      StringBuilder implementationFile,
                                      StringBuilder headerFile) {
        String generatedName = clazz.getSimpleName();

        CodeGenerator generator = new CodeGenerator(new ClassWithOptions(clazz, generatedName));

        generator.generateMembers(sortAndFilterMembers(clazz, clazz.getConstructors()));
        generator.generateMembers(sortAndFilterMembers(clazz, clazz.getMethods()));
        generator.generateMembers(sortAndFilterMembers(clazz, clazz.getFields()));

        headerFile.append(generator.getHeaderFileContents());
        implementationFile.append(generator.getWrapperFileContents());
    }

    private static Vector<String> getClassList(String path) {
        Scanner scanner = null;
        try {
            scanner = new Scanner(new FileInputStream(path));

            Vector lines = new Vector();
            while (scanner.hasNextLine()) {
                lines.add(scanner.nextLine());
            }
            return lines;
        } catch (Exception e) {
            System.out.println(e.toString());
            return null;
        } finally {
            if (scanner != null) {
                scanner.close();
            }
        }
    }

    private static void writeOutputFiles(String aOutputDir, String aPrefix, StringBuilder aHeaderFile,
                                         StringBuilder aImplementationFile) {
        FileOutputStream implStream = null;
        try {
            implStream = new FileOutputStream(new File(aOutputDir, aPrefix + ".cpp"));
            implStream.write(aImplementationFile.toString().getBytes());
        } catch (IOException e) {
            System.err.println("Unable to write " + aOutputDir + ". Perhaps a permissions issue?");
            e.printStackTrace(System.err);
        } finally {
            if (implStream != null) {
                try {
                    implStream.close();
                } catch (IOException e) {
                    System.err.println("Unable to close implStream due to "+e);
                    e.printStackTrace(System.err);
                }
            }
        }

        FileOutputStream headerStream = null;
        try {
            headerStream = new FileOutputStream(new File(aOutputDir, aPrefix + ".h"));
            headerStream.write(aHeaderFile.toString().getBytes());
        } catch (IOException e) {
            System.err.println("Unable to write " + aOutputDir + ". Perhaps a permissions issue?");
            e.printStackTrace(System.err);
        } finally {
            if (headerStream != null) {
                try {
                    headerStream.close();
                } catch (IOException e) {
                    System.err.println("Unable to close headerStream due to "+e);
                    e.printStackTrace(System.err);
                }
            }
        }
    }
}
