// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.jni_generator;

import com.google.auto.service.AutoService;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.squareup.javapoet.AnnotationSpec;
import com.squareup.javapoet.ArrayTypeName;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;

import org.chromium.base.JniStaticTestMocker;
import org.chromium.base.annotations.JniStaticNatives;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Generated;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.tools.Diagnostic;

/**
 * Annotation processor that finds inner interfaces annotated with
 * {@link JniStaticNatives} and generates a class with native bindings
 * (GEN_JNI) and a class specific wrapper class with name (classnameJni)
 *
 * NativeClass - refers to the class that contains all native declarations.
 * NativeWrapperClass - refers to the class that is generated for each class
 * containing an interface annotated with JniStaticNatives.
 *
 */
@AutoService(Processor.class)
public class JniProcessor extends AbstractProcessor {
    private static final Class<JniStaticNatives> JNI_STATIC_NATIVES_CLASS = JniStaticNatives.class;

    private static final String NATIVE_WRAPPER_CLASS_POSTFIX = "Jni";

    // The native class name and package name used in debug.
    private String mNativeClassStr = "GEN_JNI";
    private String mNativeClassPackage = "org.chromium.base.natives";
    private ClassName mNativeClassName;

    static final String NATIVE_TEST_FIELD_NAME = "TESTING_ENABLED";
    static final String NATIVE_REQUIRE_MOCK_FIELD_NAME = "REQUIRE_MOCK";

    // Lets mocks of the Native impl to be set.
    static final boolean TESTING_ENABLED = false;

    // If true, throw an exception if no mock is provided.
    private static final boolean REQUIRE_MOCK = false;

    // Builder for NativeClass which will hold all our native method declarations.
    private TypeSpec.Builder mNativesBuilder;

    // Hash function for native method names.
    private static MessageDigest sNativeMethodHashFunction;

    // If true, native methods in GEN_JNI will be named as a hash of their descriptor.
    private static final boolean USE_HASH_FOR_METHODS = !ProcessorArgs.IS_JAVA_DEBUG;
    private static final boolean USE_SHORTENED_NATIVE_CLASS = !ProcessorArgs.IS_JAVA_DEBUG;

    // Limits the number characters of the Base64 encoded hash
    // of the method descriptor used as name of the generated
    // native method in GEN_JNI (prefixed with "M")
    private static final int MAX_CHARS_FOR_HASHED_NATIVE_METHODS = 8;

    // Types that are non-primitives and should not be
    // casted to objects in native method declarations.
    static final ImmutableSet JNI_OBJECT_TYPE_EXCEPTIONS =
            ImmutableSet.of("java.lang.String", "java.lang.Throwable", "java.lang.Class", "void");

    static String getNameOfWrapperClass(String containingClassName) {
        return containingClassName + NATIVE_WRAPPER_CLASS_POSTFIX;
    }

    @Override
    public Set<String> getSupportedAnnotationTypes() {
        return ImmutableSet.of(JNI_STATIC_NATIVES_CLASS.getCanonicalName());
    }

    @Override
    public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.latestSupported();
    }

    public JniProcessor() {
        // If non-debug we use shorter names to save space.
        if (USE_SHORTENED_NATIVE_CLASS) {
            // J.N
            mNativeClassPackage = "J";
            mNativeClassStr = "N";
        }
        mNativeClassName = ClassName.get(mNativeClassPackage, mNativeClassStr);

        FieldSpec.Builder testingFlagBuilder =
                FieldSpec.builder(TypeName.BOOLEAN, NATIVE_TEST_FIELD_NAME)
                        .addModifiers(Modifier.STATIC, Modifier.PUBLIC);
        FieldSpec.Builder throwFlagBuilder =
                FieldSpec.builder(TypeName.BOOLEAN, NATIVE_REQUIRE_MOCK_FIELD_NAME)
                        .addModifiers(Modifier.STATIC, Modifier.PUBLIC);

        // Initialize only if true to avoid NoRedundantFieldInit.
        if (TESTING_ENABLED) {
            testingFlagBuilder.initializer("true");
        }
        if (REQUIRE_MOCK) {
            throwFlagBuilder.initializer("true");
        }

        // State of mNativesBuilder needs to be preserved between processing rounds.
        mNativesBuilder = TypeSpec.classBuilder(mNativeClassName)
                                  .addAnnotation(createGeneratedAnnotation())
                                  .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
                                  .addField(testingFlagBuilder.build())
                                  .addField(throwFlagBuilder.build());

        try {
            sNativeMethodHashFunction = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            // MD5 support is required for all Java platforms so this should never happen.
            printError(e.getMessage());
        }
    }

    /**
     * Processes annotations that match getSupportedAnnotationTypes()
     * Called each 'round' of annotation processing, must fail gracefully if set is empty.
     */
    @Override
    public boolean process(
            Set<? extends TypeElement> annotations, RoundEnvironment roundEnvironment) {
        // Do nothing on an empty round.
        if (annotations.isEmpty()) {
            return true;
        }

        List<JavaFile> writeQueue = Lists.newArrayList();
        for (Element e : roundEnvironment.getElementsAnnotatedWith(JNI_STATIC_NATIVES_CLASS)) {
            // @JniStaticNatives can only annotate types so this is safe.
            TypeElement type = (TypeElement) e;

            if (!e.getKind().isInterface()) {
                printError("@JniStaticNatives must annotate an interface", e);
            }

            // Interface must be nested within a class.
            Element outerElement = e.getEnclosingElement();
            if (!(outerElement instanceof TypeElement)) {
                printError(
                        "Interface annotated with @JNIInterface must be nested within a class", e);
            }

            TypeElement outerType = (TypeElement) outerElement;
            ClassName outerTypeName = ClassName.get(outerType);
            String outerClassName = outerTypeName.simpleName();
            String packageName = outerTypeName.packageName();

            // Get all methods in annotated interface.
            List<ExecutableElement> interfaceMethods = getMethodsFromType(type);

            // Map from the current method names to the method spec for a static native
            // method that will be in our big NativeClass.
            // Collisions are not allowed - no overloading.
            Map<String, MethodSpec> methodMap =
                    createNativeMethodSpecs(interfaceMethods, outerTypeName);

            // Add these to our NativeClass.
            for (MethodSpec method : methodMap.values()) {
                mNativesBuilder.addMethod(method);
            }

            // Generate a NativeWrapperClass for outerType by implementing the
            // annotated interface. Need to pass it the method map because each
            // method overridden will be a wrapper that calls its
            // native counterpart in NativeClass.
            boolean isNativesInterfacePublic = type.getModifiers().contains(Modifier.PUBLIC);
            TypeSpec nativeWrapperClassSpec =
                    createNativeWrapperClassSpec(getNameOfWrapperClass(outerClassName),
                            isNativesInterfacePublic, type, methodMap);

            // Queue this file for writing.
            // Can't write right now because the wrapper class depends on NativeClass
            // to be written and we can't write NativeClass until all @JniStaticNatives
            // interfaces are processed because each will add new native methods.
            JavaFile file = JavaFile.builder(packageName, nativeWrapperClassSpec).build();
            writeQueue.add(file);
        }

        // Nothing needs to be written this round.
        if (writeQueue.size() == 0) {
            return true;
        }

        try {
            // Need to write NativeClass first because the wrapper classes
            // depend on it.
            JavaFile nativeClassFile =
                    JavaFile.builder(mNativeClassPackage, mNativesBuilder.build()).build();

            nativeClassFile.writeTo(processingEnv.getFiler());

            for (JavaFile f : writeQueue) {
                f.writeTo(processingEnv.getFiler());
            }
        } catch (Exception e) {
            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.getMessage());
        }
        return true;
    }

    List<ExecutableElement> getMethodsFromType(TypeElement t) {
        List<ExecutableElement> methods = Lists.newArrayList();
        for (Element e : t.getEnclosedElements()) {
            if (e.getKind() == ElementKind.METHOD) {
                methods.add((ExecutableElement) e);
            }
        }
        return methods;
    }

    /**
     * Gets method name for methods inside of NativeClass
     */
    String getNativeMethodName(String packageName, String className, String oldMethodName) {
        // e.g. org.chromium.base.Foo_Class.bar
        // => org_chromium_base_Foo_1Class_bar()
        String descriptor = String.format("%s.%s.%s", packageName, className, oldMethodName)
                                    .replaceAll("_", "_1")
                                    .replaceAll("\\.", "_");
        if (USE_HASH_FOR_METHODS) {
            // Must start with a character.
            byte[] hash = sNativeMethodHashFunction.digest(descriptor.getBytes(Charsets.UTF_8));

            String methodName = "M"
                    + Base64.getEncoder()
                              .encodeToString(hash)
                              .replace("/", "_")
                              .replace("+", "$")
                              .replace("=", "");

            return methodName.substring(
                    0, Math.min(MAX_CHARS_FOR_HASHED_NATIVE_METHODS, methodName.length()));
        }
        return descriptor;
    }

    /**
     * Creates method specs for the native methods of NativeClass given
     * the method declarations from a {@link JniStaticNatives} annotated interface
     * @param interfaceMethods method declarations from a {@link JniStaticNatives} annotated
     * interface
     * @param outerType ClassName of class that contains the annotated interface
     * @return map from old method name to new native method specification
     */
    Map<String, MethodSpec> createNativeMethodSpecs(
            List<ExecutableElement> interfaceMethods, ClassName outerType) {
        Map<String, MethodSpec> methodMap = Maps.newTreeMap();
        for (ExecutableElement m : interfaceMethods) {
            String oldMethodName = m.getSimpleName().toString();
            String newMethodName = getNativeMethodName(
                    outerType.packageName(), outerType.simpleName(), oldMethodName);
            MethodSpec.Builder builder = MethodSpec.methodBuilder(newMethodName)
                                                 .addModifiers(Modifier.PUBLIC)
                                                 .addModifiers(Modifier.FINAL)
                                                 .addModifiers(Modifier.STATIC)
                                                 .addModifiers(Modifier.NATIVE);
            builder.addJavadoc(createNativeMethodJavadocString(outerType, m));

            copyMethodParamsAndReturnType(builder, m, true);
            if (methodMap.containsKey(oldMethodName)) {
                printError("Overloading is not currently implemented with this processor ", m);
            }
            methodMap.put(oldMethodName, builder.build());
        }
        return methodMap;
    }

    /**
     * Creates a generated annotation that contains the name of this class.
     */
    static AnnotationSpec createGeneratedAnnotation() {
        return AnnotationSpec.builder(Generated.class)
                .addMember("value", String.format("\"%s\"", JniProcessor.class.getCanonicalName()))
                .build();
    }

    void printError(String s) {
        processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, s);
    }

    void printError(String s, Element e) {
        processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
                String.format("Error processing @JniStaticNatives interface: %s", s), e);
    }

    /**
     * Creates a class spec for an implementation of an {@link JniStaticNatives} annotated interface
     * that will wrap calls to the NativesClass which contains the actual native method
     * declarations.
     *
     * This class should contain:
     * 1. Wrappers for all GEN_JNI static native methods
     * 2. A getter that when testing is disabled, will return the native implementation and
     * when testing is enabled, will call the mock of the native implementation.
     * 3. A field that holds the testNatives instance for when testing is enabled
     * 4. A TEST_HOOKS field that implements an anonymous instance of {@link JniStaticTestMocker}
     * which will set the testNatives implementation when called in tests
     *
     * @param name name of the wrapper class.
     * @param isPublic if true, a public modifier will be added to this native wrapper.
     * @param nativeInterface the {@link JniStaticNatives} annotated type that this native wrapper
     *                        will implement.
     * @param methodMap a map from the old method name to the new method spec in NativeClass.
     * */
    TypeSpec createNativeWrapperClassSpec(String name, boolean isPublic,
            TypeElement nativeInterface, Map<String, MethodSpec> methodMap) {
        // The wrapper class builder.
        TypeName nativeInterfaceType = TypeName.get(nativeInterface.asType());
        TypeSpec.Builder builder = TypeSpec.classBuilder(name)
                                           .addSuperinterface(nativeInterfaceType)
                                           .addModifiers(Modifier.FINAL)
                                           .addAnnotation(createGeneratedAnnotation());
        if (isPublic) {
            builder.addModifiers(Modifier.PUBLIC);
        }

        // Start by adding all the native method wrappers.
        for (Element enclosed : nativeInterface.getEnclosedElements()) {
            if (enclosed.getKind() != ElementKind.METHOD) {
                printError("Cannot have a non-method in a @JniStaticNatives annotated interface",
                        enclosed);
            }

            // ElementKind.Method is ExecutableElement so this cast is safe.
            // interfaceMethod will is the method we are overloading.
            ExecutableElement interfaceMethod = (ExecutableElement) enclosed;

            // Method in NativesClass that we'll be calling.
            MethodSpec nativesMethod = methodMap.get(interfaceMethod.getSimpleName().toString());

            // Add a matching method in this class that overrides the declaration
            // in nativeInterface. It will just call the actual natives method in
            // NativeClass.
            builder.addMethod(createNativeWrapperMethod(interfaceMethod, nativesMethod));
        }

        // Add the testInstance field.
        // Holds the test natives target if it is set.
        FieldSpec testTarget = FieldSpec.builder(nativeInterfaceType, "testInstance")
                                       .addModifiers(Modifier.PRIVATE, Modifier.STATIC)
                                       .build();
        builder.addField(testTarget);

        // Getter for target or testing instance if flag in GEN_JNI is set.
        /*
        {classname}.Natives get() {
            if (GEN_JNI.TESTING_ENABLED) {
                if (testInst != null) {
                    return testInst;
                }
                if (GEN_JNI.REQUIRE_MOCK) {
                    throw new UnsupportedOperationException($noMockExceptionString);
                }
            }
            return new {classname}Jni();
        }
         */
        String noMockExceptionString =
                String.format("No mock found for the native implementation for %s. "
                                + "The current configuration requires all native "
                                + "implementations to have a mock instance.",
                        nativeInterfaceType);
        MethodSpec instanceGetter =
                MethodSpec.methodBuilder("get")
                        .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
                        .returns(nativeInterfaceType)
                        .beginControlFlow("if ($T.$N)", mNativeClassName, NATIVE_TEST_FIELD_NAME)
                        .beginControlFlow("if ($N != null)", testTarget)
                        .addStatement("return $N", testTarget)
                        .endControlFlow()
                        .beginControlFlow(
                                "if ($T.$N)", mNativeClassName, NATIVE_REQUIRE_MOCK_FIELD_NAME)
                        .addStatement("throw new UnsupportedOperationException($S)",
                                noMockExceptionString)
                        .endControlFlow()
                        .endControlFlow()
                        .addStatement("return new $N()", name)
                        .build();

        builder.addMethod(instanceGetter);

        // Next add TEST_HOOKS to set testInstance... should look like this:
        // JniStaticTestMocker<ClassNameJni> TEST_HOOKS = new JniStaticTestMocker<>() {
        //      @Override
        //      public static setInstanceForTesting(ClassNameJni instance) {
        //          testInstance = instance;
        //      }
        // }
        MethodSpec testHookMockerMethod = MethodSpec.methodBuilder("setInstanceForTesting")
                                                  .addModifiers(Modifier.PUBLIC)
                                                  .addAnnotation(Override.class)
                                                  .addParameter(nativeInterfaceType, "instance")
                                                  .addStatement("$N = instance", testTarget)
                                                  .build();

        // Make the anonymous TEST_HOOK class.
        ParameterizedTypeName genericMockerInterface = ParameterizedTypeName.get(
                ClassName.get(JniStaticTestMocker.class), ClassName.get(nativeInterface));

        TypeSpec testHook = TypeSpec.anonymousClassBuilder("")
                                    .addSuperinterface(genericMockerInterface)
                                    .addMethod(testHookMockerMethod)
                                    .build();

        FieldSpec testHookSpec =
                FieldSpec.builder(genericMockerInterface, "TEST_HOOKS")
                        .addModifiers(Modifier.STATIC, Modifier.PUBLIC, Modifier.FINAL)
                        .initializer("$L", testHook.toString())
                        .build();

        builder.addField(testHookSpec);
        return builder.build();
    }

    /**
     * Creates a wrapper method that overrides interfaceMethod and calls staticNativeMethod.
     * @param interfaceMethod method that will be overridden in a {@link JniStaticNatives} annotated
     * interface.
     * @param staticNativeMethod method that will be called in NativeClass.
     */
    MethodSpec createNativeWrapperMethod(
            ExecutableElement interfaceMethod, MethodSpec staticNativeMethod) {
        // Method will have the same name and be public.
        MethodSpec.Builder builder =
                MethodSpec.methodBuilder(interfaceMethod.getSimpleName().toString())
                        .addModifiers(Modifier.PUBLIC)
                        .addAnnotation(Override.class);

        // Method will need the same params and return type as the one we're overriding.
        copyMethodParamsAndReturnType(builder, interfaceMethod);

        // Add return if method return type is not void.
        if (!interfaceMethod.getReturnType().toString().equals("void")) {
            // Also need to cast because non-primitives are Objects in NativeClass.
            builder.addCode("return ($T)", interfaceMethod.getReturnType());
        }

        // Make call to native function.
        builder.addCode("$T.$N(", mNativeClassName, staticNativeMethod);

        // Add params to native call.
        ArrayList<String> paramNames = new ArrayList<>();
        for (VariableElement param : interfaceMethod.getParameters()) {
            paramNames.add(param.getSimpleName().toString());
        }

        builder.addCode(String.join(", ", paramNames) + ");\n");
        return builder.build();
    }

    void copyMethodParamsAndReturnType(MethodSpec.Builder builder, ExecutableElement method) {
        copyMethodParamsAndReturnType(builder, method, false);
    }

    boolean shouldDowncastToObjectForJni(TypeName t) {
        if (t.isPrimitive()) {
            return false;
        }
        // There are some non-primitives that should not be downcasted.
        return !JNI_OBJECT_TYPE_EXCEPTIONS.contains(t.toString());
    }

    TypeName toTypeName(TypeMirror t, boolean useJni) {
        if (t.getKind() == TypeKind.ARRAY) {
            return ArrayTypeName.of(toTypeName(((ArrayType) t).getComponentType(), useJni));
        }
        TypeName typeName = TypeName.get(t);
        if (useJni && shouldDowncastToObjectForJni(typeName)) {
            return TypeName.OBJECT;
        }
        return typeName;
    }

    /**
     * Since some types may decay to objects in the native method
     * this method returns a javadoc string that contains the
     * type information from the old method. The fully qualified
     * descriptor of the method is also included since the name
     * may be hashed.
     */
    String createNativeMethodJavadocString(ClassName outerType, ExecutableElement oldMethod) {
        ArrayList<String> docLines = new ArrayList<>();

        // Class descriptor.
        String descriptor = String.format("%s.%s.%s", outerType.packageName(),
                outerType.simpleName(), oldMethod.getSimpleName().toString());
        docLines.add(descriptor);

        // Parameters.
        for (VariableElement param : oldMethod.getParameters()) {
            TypeName paramType = TypeName.get(param.asType());
            String paramTypeName = paramType.toString();
            String name = param.getSimpleName().toString();
            docLines.add(String.format("@param %s (%s)", name, paramTypeName));
        }

        // Return type.
        docLines.add(String.format("@return (%s)", oldMethod.getReturnType().toString()));

        return String.join("\n", docLines) + "\n";
    }

    void copyMethodParamsAndReturnType(
            MethodSpec.Builder builder, ExecutableElement method, boolean useJniTypes) {
        for (VariableElement param : method.getParameters()) {
            builder.addParameter(createParamSpec(param, useJniTypes));
        }
        TypeMirror givenReturnType = method.getReturnType();
        TypeName returnType = toTypeName(givenReturnType, useJniTypes);

        builder.returns(returnType);
    }

    ParameterSpec createParamSpec(VariableElement param, boolean useJniObjects) {
        TypeName paramType = toTypeName(param.asType(), useJniObjects);
        return ParameterSpec.builder(paramType, param.getSimpleName().toString())
                .addModifiers(param.getModifiers())
                .build();
    }
}
