// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

package com.android.tools.r8;

import com.android.tools.r8.cf.code.CfConstNull;
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfThrow;
import com.android.tools.r8.dex.ApplicationReader;
import com.android.tools.r8.dex.Marker.Tool;
import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexLibraryClass;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexProgramClass.ChecksumSupplier;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DirectMappedDexApplication;
import com.android.tools.r8.graph.GraphLense;
import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration;
import com.android.tools.r8.ir.desugar.DesugaredLibraryConfigurationParser;
import com.android.tools.r8.jar.CfApplicationWriter;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.Timing;
import com.google.common.collect.Sets;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.function.BiPredicate;
import java.util.function.Predicate;

public class GenerateLintFiles {

  private static final String ANDROID_JAR_PATTERN = "third_party/android_jar/lib-v%d/android.jar";

  private final DexItemFactory factory = new DexItemFactory();
  private final Reporter reporter = new Reporter();
  private final InternalOptions options = new InternalOptions(factory, reporter);

  private final DesugaredLibraryConfiguration desugaredLibraryConfiguration;
  private final String outputDirectory;

  private final Set<DexMethod> parallelMethods = Sets.newIdentityHashSet();

  private GenerateLintFiles(String desugarConfigurationPath, String outputDirectory) {
    this.desugaredLibraryConfiguration =
        readDesugaredLibraryConfiguration(desugarConfigurationPath);
    this.outputDirectory =
        outputDirectory.endsWith("/") ? outputDirectory : outputDirectory + File.separator;

    DexType streamType = factory.createType(factory.createString("Ljava/util/stream/Stream;"));
    DexMethod parallelMethod =
        factory.createMethod(
            factory.collectionType,
            factory.createProto(streamType),
            factory.createString("parallelStream"));
    parallelMethods.add(parallelMethod);
    DexType baseStreamType =
        factory.createType(factory.createString("Ljava/util/stream/BaseStream;"));
    for (String typePrefix : new String[] {"Base", "Double", "Int", "Long"}) {
      streamType =
          factory.createType(factory.createString("Ljava/util/stream/" + typePrefix + "Stream;"));
      parallelMethod =
          factory.createMethod(
              streamType, factory.createProto(streamType), factory.createString("parallel"));
      parallelMethods.add(parallelMethod);
      // Also filter out the generated bridges for the covariant return type.
      parallelMethod =
          factory.createMethod(
              streamType, factory.createProto(baseStreamType), factory.createString("parallel"));
      parallelMethods.add(parallelMethod);
    }
  }

  private static Path getAndroidJarPath(AndroidApiLevel apiLevel) {
    String jar = String.format(ANDROID_JAR_PATTERN, apiLevel.getLevel());
    return Paths.get(jar);
  }

  private DesugaredLibraryConfiguration readDesugaredLibraryConfiguration(
      String desugarConfigurationPath) {
    return new DesugaredLibraryConfigurationParser(
            factory, reporter, false, AndroidApiLevel.B.getLevel())
        .parse(StringResource.fromFile(Paths.get(desugarConfigurationPath)));
  }

  private CfCode buildEmptyThrowingCfCode(DexMethod method) {
    CfInstruction insn[] = {new CfConstNull(), new CfThrow()};
    return new CfCode(
        method.holder,
        1,
        method.proto.parameters.size() + 1,
        Arrays.asList(insn),
        Collections.emptyList(),
        Collections.emptyList());
  }

  private void addMethodsToHeaderJar(
      DexApplication.Builder builder, DexClass clazz, List<DexEncodedMethod> methods) {
    if (methods.size() == 0) {
      return;
    }

    List<DexEncodedMethod> directMethods = new ArrayList<>();
    List<DexEncodedMethod> virtualMethods = new ArrayList<>();
    for (DexEncodedMethod method : methods) {
      assert method.holder() == clazz.type;
      CfCode code = null;
      if (!method.accessFlags.isAbstract() /*&& !method.accessFlags.isNative()*/) {
        code = buildEmptyThrowingCfCode(method.method);
      }
      DexEncodedMethod throwingMethod =
          new DexEncodedMethod(
              method.method,
              method.accessFlags,
              DexAnnotationSet.empty(),
              ParameterAnnotationsList.empty(),
              code,
              50);
      if (method.isStatic() || method.isDirectMethod()) {
        directMethods.add(throwingMethod);
      } else {
        virtualMethods.add(throwingMethod);
      }
    }

    DexEncodedMethod[] directMethodsArray = new DexEncodedMethod[directMethods.size()];
    DexEncodedMethod[] virtualMethodsArray = new DexEncodedMethod[virtualMethods.size()];
    directMethods.toArray(directMethodsArray);
    virtualMethods.toArray(virtualMethodsArray);
    assert !options.encodeChecksums;
    ChecksumSupplier checksumSupplier = DexProgramClass::invalidChecksumRequest;
    DexProgramClass programClass =
        new DexProgramClass(
            clazz.type,
            null,
            Origin.unknown(),
            clazz.accessFlags,
            clazz.superType,
            clazz.interfaces,
            null,
            null,
            Collections.emptyList(),
            null,
            Collections.emptyList(),
            DexAnnotationSet.empty(),
            DexEncodedField.EMPTY_ARRAY,
            DexEncodedField.EMPTY_ARRAY,
            directMethodsArray,
            virtualMethodsArray,
            false,
            checksumSupplier);
    builder.addProgramClass(programClass);
  }

  public static class SupportedMethods {
    public final Set<DexClass> classesWithAllMethodsSupported;
    public final Map<DexClass, List<DexEncodedMethod>> supportedMethods;

    public SupportedMethods(
        Set<DexClass> classesWithAllMethodsSupported,
        Map<DexClass, List<DexEncodedMethod>> supportedMethods) {
      this.classesWithAllMethodsSupported = classesWithAllMethodsSupported;
      this.supportedMethods = supportedMethods;
    }
  }

  private SupportedMethods collectSupportedMethods(
      AndroidApiLevel compilationApiLevel, Predicate<DexEncodedMethod> supported)
      throws IOException, ExecutionException {

    // Read the android.jar for the compilation API level.
    AndroidApp library =
        AndroidApp.builder().addLibraryFiles(getAndroidJarPath(compilationApiLevel)).build();
    DirectMappedDexApplication dexApplication =
        new ApplicationReader(library, options, Timing.empty()).read().toDirect();

    // Collect all the methods that the library desugar configuration adds support for.
    Set<DexClass> classesWithAllMethodsSupported = Sets.newIdentityHashSet();
    Map<DexClass, List<DexEncodedMethod>> supportedMethods = new LinkedHashMap<>();
    for (DexLibraryClass clazz : dexApplication.libraryClasses()) {
      String className = clazz.toSourceString();
      // All the methods with the rewritten prefix are supported.
      for (String prefix : desugaredLibraryConfiguration.getRewritePrefix().keySet()) {
        if (clazz.accessFlags.isPublic() && className.startsWith(prefix)) {
          boolean allMethodsAddad = true;
          for (DexEncodedMethod method : clazz.methods()) {
            if (supported.test(method)) {
              supportedMethods.computeIfAbsent(clazz, k -> new ArrayList<>()).add(method);
            } else {
              allMethodsAddad = false;
            }
          }
          if (allMethodsAddad) {
            classesWithAllMethodsSupported.add(clazz);
          }
        }
      }

      // All retargeted methods are supported.
      for (DexEncodedMethod method : clazz.methods()) {
        if (desugaredLibraryConfiguration
            .getRetargetCoreLibMember()
            .keySet()
            .contains(method.method.name)) {
          if (desugaredLibraryConfiguration
              .getRetargetCoreLibMember()
              .get(method.method.name)
              .containsKey(clazz.type)) {
            if (supported.test(method)) {
              supportedMethods.computeIfAbsent(clazz, k -> new ArrayList<>()).add(method);
            }
          }
        }
      }

      // All emulated interfaces static and default methods are supported.
      if (desugaredLibraryConfiguration.getEmulateLibraryInterface().containsKey(clazz.type)) {
        assert clazz.isInterface();
        for (DexEncodedMethod method : clazz.methods()) {
          if (!method.isDefaultMethod() && !method.isStatic()) {
            continue;
          }
          if (supported.test(method)) {
            supportedMethods.computeIfAbsent(clazz, k -> new ArrayList<>()).add(method);
          }
        }
      }
    }

    return new SupportedMethods(classesWithAllMethodsSupported, supportedMethods);
  }

  private String lintBaseFileName(
      AndroidApiLevel compilationApiLevel, AndroidApiLevel minApiLevel) {
    return "desugared_apis_" + compilationApiLevel.getLevel() + "_" + minApiLevel.getLevel();
  }

  private Path lintFile(
      AndroidApiLevel compilationApiLevel, AndroidApiLevel minApiLevel, String extension)
      throws Exception {
    Path directory =
        Paths.get(outputDirectory + "compile_api_level_" + compilationApiLevel.getLevel());
    Files.createDirectories(directory);
    return Paths.get(
        directory
            + File.separator
            + lintBaseFileName(compilationApiLevel, minApiLevel)
            + extension);
  }

  private void writeLintFiles(
      AndroidApiLevel compilationApiLevel,
      AndroidApiLevel minApiLevel,
      SupportedMethods supportedMethods)
      throws Exception {
    // Build a plain text file with the desugared APIs.
    List<String> desugaredApisSignatures = new ArrayList<>();

    DexApplication.Builder builder = DexApplication.builder(options, Timing.empty());
    supportedMethods.supportedMethods.forEach(
        (clazz, methods) -> {
          String classBinaryName =
              DescriptorUtils.getClassBinaryNameFromDescriptor(clazz.type.descriptor.toString());
          if (!supportedMethods.classesWithAllMethodsSupported.contains(clazz)) {
            for (DexEncodedMethod method : methods) {
              desugaredApisSignatures.add(
                  classBinaryName
                      + '#'
                      + method.method.name
                      + method.method.proto.toDescriptorString());
            }
          } else {
            desugaredApisSignatures.add(classBinaryName);
          }

          addMethodsToHeaderJar(builder, clazz, methods);
        });
    DexApplication app = builder.build();

    // Write a plain text file with the desugared APIs.
    desugaredApisSignatures.sort(Comparator.naturalOrder());
    FileUtils.writeTextFile(
        lintFile(compilationApiLevel, minApiLevel, ".txt"), desugaredApisSignatures);

    // Write a header jar with the desugared APIs.
    AppInfo appInfo = new AppInfo(app);
    AppView<?> appView = AppView.createForD8(appInfo, options);
    CfApplicationWriter writer =
        new CfApplicationWriter(
            builder.build(),
            appView,
            options,
            options.getMarker(Tool.L8),
            GraphLense.getIdentityLense(),
            NamingLens.getIdentityLens(),
            null);
    ClassFileConsumer consumer =
        new ClassFileConsumer.ArchiveConsumer(
            lintFile(compilationApiLevel, minApiLevel, FileUtils.JAR_EXTENSION));
    writer.write(consumer);
    consumer.finished(options.reporter);
  }

  private void generateLintFiles(
      AndroidApiLevel compilationApiLevel,
      Predicate<AndroidApiLevel> generateForThisMinApiLevel,
      BiPredicate<AndroidApiLevel, DexEncodedMethod> supportedForMinApiLevel)
      throws Exception {
    System.out.print("  - generating for min API:");
    for (AndroidApiLevel minApiLevel : AndroidApiLevel.values()) {
      if (!generateForThisMinApiLevel.test(minApiLevel)) {
        continue;
      }

      System.out.print(" " + minApiLevel);

      SupportedMethods supportedMethods =
          collectSupportedMethods(
              compilationApiLevel, (method -> supportedForMinApiLevel.test(minApiLevel, method)));
      writeLintFiles(compilationApiLevel, minApiLevel, supportedMethods);
    }
    System.out.println();
  }

  private void run() throws Exception {
    // Run over all the API levels that the desugared library can be compiled with.
    for (int apiLevel = AndroidApiLevel.Q.getLevel();
        apiLevel >= desugaredLibraryConfiguration.getRequiredCompilationApiLevel().getLevel();
        apiLevel--) {
      System.out.println("Generating lint files for compile API " + apiLevel);
      generateLintFiles(
          AndroidApiLevel.getAndroidApiLevel(apiLevel),
          minApiLevel -> minApiLevel == AndroidApiLevel.L || minApiLevel == AndroidApiLevel.B,
          (minApiLevel, method) -> {
            assert minApiLevel == AndroidApiLevel.L || minApiLevel == AndroidApiLevel.B;
            if (minApiLevel == AndroidApiLevel.L) {
              return true;
            }
            assert minApiLevel == AndroidApiLevel.B;
            return !parallelMethods.contains(method.method);
          });
    }
  }

  public static void main(String[] args) throws Exception {
    if (args.length != 2) {
      System.out.println("Usage: GenerateLineFiles <desuage configuration> <output directory>");
      System.exit(1);
    }
    new GenerateLintFiles(args[0], args[1]).run();
  }
}
