// Copyright 2018 The Bazel Authors. All rights reserved.
//
// 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 com.google.devtools.build.android.desugar.scan;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static java.nio.file.StandardOpenOption.CREATE;
import static java.util.Comparator.comparing;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.ByteStreams;
import com.google.common.io.Closer;
import com.google.devtools.build.android.Converters.ExistingPathConverter;
import com.google.devtools.build.android.Converters.PathConverter;
import com.google.devtools.build.android.desugar.io.CoreLibraryRewriter;
import com.google.devtools.build.android.desugar.io.HeaderClassLoader;
import com.google.devtools.build.android.desugar.io.IndexedInputs;
import com.google.devtools.build.android.desugar.io.InputFileProvider;
import com.google.devtools.build.android.desugar.io.ThrowingClassLoader;
import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionDocumentationCategory;
import com.google.devtools.common.options.OptionEffectTag;
import com.google.devtools.common.options.OptionsBase;
import com.google.devtools.common.options.OptionsParser;
import com.google.devtools.common.options.ShellQuotedParamsFilePreProcessor;
import java.io.IOError;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.lang.reflect.Method;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Type;

class KeepScanner {

  public static class KeepScannerOptions extends OptionsBase {
    @Option(
        name = "input",
        defaultValue = "null",
        documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
        effectTags = OptionEffectTag.UNKNOWN,
        converter = ExistingPathConverter.class,
        abbrev = 'i',
        help = "Input Jar with classes to scan.")
    public Path inputJars;

    @Option(
        name = "classpath_entry",
        allowMultiple = true,
        defaultValue = "null",
        documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
        effectTags = {OptionEffectTag.UNKNOWN},
        converter = ExistingPathConverter.class,
        help =
            "Ordered classpath (Jar or directory) to resolve symbols in the --input Jar, like "
                + "javac's -cp flag.")
    public List<Path> classpath;

    @Option(
        name = "bootclasspath_entry",
        allowMultiple = true,
        defaultValue = "null",
        documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
        effectTags = {OptionEffectTag.UNKNOWN},
        converter = ExistingPathConverter.class,
        help =
            "Bootclasspath that was used to compile the --input Jar with, like javac's "
                + "-bootclasspath flag (required).")
    public List<Path> bootclasspath;

    @Option(
        name = "keep_file",
        defaultValue = "null",
        documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
        effectTags = OptionEffectTag.UNKNOWN,
        converter = PathConverter.class,
        help = "Where to write keep rules to.")
    public Path keepDest;

    @Option(
        name = "prefix",
        defaultValue = "j$/",
        documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
        effectTags = OptionEffectTag.UNKNOWN,
        help = "type to scan for.")
    public String prefix;
  }

  public static void main(String... args) throws Exception {
    OptionsParser parser =
        OptionsParser.builder()
            .optionsClasses(KeepScannerOptions.class)
            .allowResidue(false)
            .argsPreProcessor(new ShellQuotedParamsFilePreProcessor(FileSystems.getDefault()))
            .build();
    parser.parseAndExitUponError(args);
    KeepScannerOptions options = parser.getOptions(KeepScannerOptions.class);

    Map<String, ImmutableSet<KeepReference>> seeds;
    try (Closer closer = Closer.create()) {
      // TODO(kmb): Try to share more of this code with Desugar binary
      IndexedInputs classpath =
          new IndexedInputs(toRegisteredInputFileProvider(closer, options.classpath));
      IndexedInputs bootclasspath =
          new IndexedInputs(toRegisteredInputFileProvider(closer, options.bootclasspath));

      // Construct classloader from classpath.  Since we're assuming the prefix we're looking for
      // isn't part of the input itself we shouldn't need to include the input in the classloader.
      CoreLibraryRewriter noopRewriter = new CoreLibraryRewriter("");
      ClassLoader classloader =
          new HeaderClassLoader(
              classpath,
              noopRewriter,
              new HeaderClassLoader(bootclasspath, noopRewriter, new ThrowingClassLoader()));
      seeds = scan(checkNotNull(options.inputJars), options.prefix, classloader);
    }

    try (PrintStream out =
        new PrintStream(
            Files.newOutputStream(options.keepDest, CREATE), /*autoFlush=*/ false, "UTF-8")) {
      writeKeepDirectives(out, seeds);
    }
  }

  /**
   * Writes a -keep rule for each class listing any members to keep. We sort classes and members so
   * the output is deterministic.
   */
  private static void writeKeepDirectives(
      PrintStream out, Map<String, ImmutableSet<KeepReference>> seeds) {
    seeds.entrySet().stream()
        .sorted(comparing(Map.Entry::getKey))
        .forEachOrdered(
            type -> {
              out.printf("-keep class %s {%n", type.getKey().replace('/', '.'));
              type.getValue().stream()
                  .filter(KeepReference::isMemberReference)
                  .sorted(comparing(KeepReference::name).thenComparing(KeepReference::desc))
                  .map(ref -> toKeepDescriptor(ref))
                  .distinct() // drop duplicates due to method descriptors with different returns
                  .forEachOrdered(line -> out.append("  ").append(line).append(";").println());
              out.printf("}%n");
            });
  }

  /** Scans for and returns references with owners matching the given prefix grouped by owner. */
  private static Map<String, ImmutableSet<KeepReference>> scan(
      Path jarFile, String prefix, ClassLoader classpath) throws IOException {
    // We read the Jar sequentially since ZipFile uses locks anyway but then allow scanning each
    // class in parallel.
    try (ZipFile zip = new ZipFile(jarFile.toFile())) {
      return zip.stream()
          .filter(entry -> entry.getName().endsWith(".class"))
          .map(entry -> readFully(zip, entry))
          .parallel()
          .flatMap(
              content -> PrefixReferenceScanner.scan(new ClassReader(content), prefix).stream())
          .distinct() // so we don't process the same reference multiple times next
          .map(ref -> nearestDeclaration(ref, classpath))
          .collect(
              Collectors.groupingByConcurrent(
                  KeepReference::internalName, ImmutableSet.toImmutableSet()));
    }
  }

  private static byte[] readFully(ZipFile zip, ZipEntry entry) {
    byte[] result = new byte[(int) entry.getSize()];
    try (InputStream content = zip.getInputStream(entry)) {
      ByteStreams.readFully(content, result);
      return result;
    } catch (IOException e) {
      throw new IOError(e);
    }
  }

  /**
   * Find the nearest definition of the given reference in the class hierarchy and return the
   * modified reference. This is needed b/c bytecode sometimes refers to a method or field using an
   * owner type that inherits the method or field instead of defining the member itself. In that
   * case we need to find and keep the inherited definition.
   */
  private static KeepReference nearestDeclaration(KeepReference ref, ClassLoader classpath) {
    if (!ref.isMemberReference() || "<init>".equals(ref.name())) {
      return ref; // class and constructor references don't need any further work
    }

    Class<?> clazz;
    try {
      clazz = classpath.loadClass(ref.internalName().replace('/', '.'));
    } catch (ClassNotFoundException e) {
      throw (NoClassDefFoundError) new NoClassDefFoundError("Couldn't load " + ref).initCause(e);
    }

    Class<?> owner = findDeclaringClass(clazz, ref);
    if (owner == clazz) {
      return ref;
    }
    String parent = checkNotNull(owner, "Can't resolve: %s", ref).getName().replace('.', '/');
    return KeepReference.memberReference(parent, ref.name(), ref.desc());
  }

  private static Class<?> findDeclaringClass(Class<?> clazz, KeepReference ref) {
    if (ref.isFieldReference()) {
      try {
        return clazz.getField(ref.name()).getDeclaringClass();
      } catch (NoSuchFieldException e) {
        // field must be non-public, so search class hierarchy
        do {
          try {
            return clazz.getDeclaredField(ref.name()).getDeclaringClass();
          } catch (NoSuchFieldException ignored) {
            // fall through for clarity
          }
          clazz = clazz.getSuperclass();
        } while (clazz != null);
      }
    } else {
      checkState(ref.isMethodReference());
      Type descriptor = Type.getMethodType(ref.desc());
      for (Method m : clazz.getMethods()) {
        if (m.getName().equals(ref.name()) && Type.getType(m).equals(descriptor)) {
          return m.getDeclaringClass();
        }
      }
      do {
        // Method must be non-public, so search class hierarchy
        for (Method m : clazz.getDeclaredMethods()) {
          if (m.getName().equals(ref.name()) && Type.getType(m).equals(descriptor)) {
            return m.getDeclaringClass();
          }
        }
        clazz = clazz.getSuperclass();
      } while (clazz != null);
    }
    return null;
  }

  private static CharSequence toKeepDescriptor(KeepReference member) {
    StringBuilder result = new StringBuilder();
    if (member.isMethodReference()) {
      if (!"<init>".equals(member.name())) {
        result.append("*** ");
      }
      result.append(member.name()).append("(");
      // Ignore return type as it's unique in the source language
      boolean first = true;
      for (Type param : Type.getMethodType(member.desc()).getArgumentTypes()) {
        if (first) {
          first = false;
        } else {
          result.append(", ");
        }
        result.append(param.getClassName());
      }
      result.append(")");
    } else {
      checkArgument(member.isFieldReference());
      result.append("*** ").append(member.name()); // field names are unique so ignore descriptor
    }
    return result;
  }

  /**
   * Transform a list of Path to a list of InputFileProvider and register them with the given
   * closer.
   */
  @SuppressWarnings("MustBeClosedChecker")
  private static ImmutableList<InputFileProvider> toRegisteredInputFileProvider(
      Closer closer, List<Path> paths) throws IOException {
    ImmutableList.Builder<InputFileProvider> builder = new ImmutableList.Builder<>();
    for (Path path : paths) {
      builder.add(closer.register(InputFileProvider.open(path)));
    }
    return builder.build();
  }

  private KeepScanner() {}
}
