// 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.importdeps;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.io.MoreFiles.asCharSink;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.devtools.build.lib.view.proto.Deps.Dependencies;
import com.google.devtools.common.options.Converter;
import com.google.devtools.common.options.EnumConverter;
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.OptionsParsingException;
import com.google.devtools.common.options.ShellQuotedParamsFilePreProcessor;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;

/**
 * A checker that checks the completeness of the dependencies of an import target (java_import or
 * aar_import). If incomplete, it prints out the list of missing class names to the output file.
 */
public class Main {

  /** Command line options. */
  public static class Options extends OptionsBase {
    @Option(
      name = "input",
      allowMultiple = true,
      defaultValue = "",
      category = "input",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.UNKNOWN},
      converter = ExistingPathConverter.class,
      abbrev = 'i',
      help = "Input jars with classes to check the completeness of their dependencies."
    )
    public List<Path> inputJars;

    @Option(
      name = "directdep",
      allowMultiple = true,
      defaultValue = "",
      category = "input",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.UNKNOWN},
      converter = ExistingPathConverter.class,
      help = "Subset of Jars listed in --classpath_entry that --input Jars are allowed to depend "
          + "on directly."
    )
    public List<Path> directClasspath;

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

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

    @Option(
      name = "output",
      defaultValue = "null",
      category = "output",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.UNKNOWN},
      converter = PathConverter.class,
      help = "Output path to save the result."
    )
    public Path output;

    @Option(
        name = "jdeps_output",
        defaultValue = "null",
        category = "output",
        documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
        effectTags = {OptionEffectTag.UNKNOWN},
        converter = PathConverter.class,
        help = "Output path to save the result.")
    public Path jdepsOutput;

    @Option(
        name = "rule_label",
        defaultValue = "",
        category = "output",
        documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
        effectTags = {OptionEffectTag.UNKNOWN},
        help = "The rule label of the current target under analysis.")
    public String ruleLabel;

    @Option(
      name = "checking_mode",
      defaultValue = "WARNING",
      documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
      effectTags = {OptionEffectTag.UNKNOWN},
      converter = CheckingModeConverter.class,
      help = "Controls the behavior of the checker."
    )
    public CheckingMode checkingMode;
  }

  /** A randomly picked large exit code to avoid collision with other common exit codes. */
  private static final int DEPS_ERROR_EXIT_CODE = 199;

  public static void main(String[] args) throws IOException {
    System.exit(checkDeps(args));
  }

  @VisibleForTesting
  static int checkDeps(String[] args) throws IOException {
    Options options = parseCommandLineOptions(args);

    if (!Files.exists(options.output)) {
      Files.createFile(options.output); // Make sure the output file always exists.
    }

    int exitCode = 0;
    try (ImportDepsChecker checker =
        new ImportDepsChecker(
            ImmutableList.copyOf(options.bootclasspath),
            // Consider everything direct if no direct classpath is given
            options.directClasspath.isEmpty()
                ? ImmutableList.copyOf(options.fullClasspath)
                : ImmutableList.copyOf(options.directClasspath),
            ImmutableList.copyOf(options.fullClasspath),
            ImmutableList.copyOf(options.inputJars))) {
      if (!checker.check() && options.checkingMode != CheckingMode.SILENCE) {
        String result = checker.computeResultOutput(options.ruleLabel);
        checkState(!result.isEmpty(), "The result should NOT be empty.");
        exitCode = options.checkingMode == CheckingMode.ERROR ? DEPS_ERROR_EXIT_CODE : 0;
        printErrorMessage(result, options);
        asCharSink(options.output, StandardCharsets.UTF_8).write(result);
      }
      if (options.jdepsOutput != null) {
        Dependencies dependencies = checker.emitJdepsProto(options.ruleLabel);
        try (OutputStream os =
            new BufferedOutputStream(Files.newOutputStream(options.jdepsOutput))) {
          dependencies.writeTo(os);
        }
      }
    }
    return exitCode;
  }

  private static void printErrorMessage(String detailedErrorMessage, Options options) {
    checkArgument(
        options.checkingMode == CheckingMode.ERROR || options.checkingMode == CheckingMode.WARNING);
    System.err.print(options.checkingMode == CheckingMode.ERROR ? "ERROR" : "WARNING");
    System.err.printf(
        ": The dependencies for the following %d jar(s) are not complete.\n",
        options.inputJars.size());
    int index = 1;
    for (Path jar : options.inputJars) {
      System.err.printf("    %3d.%s\n", index++, jar.toString());
    }
    System.err.println("The details are listed below:");
    System.err.print(detailedErrorMessage);
  }

  @VisibleForTesting
  static Options parseCommandLineOptions(String[] args) throws IOException {
    OptionsParser optionsParser = OptionsParser.newOptionsParser(Options.class);
    optionsParser.setAllowResidue(false);
    optionsParser.enableParamsFileSupport(
        new ShellQuotedParamsFilePreProcessor(FileSystems.getDefault()));
    optionsParser.parseAndExitUponError(args);
    Options options = optionsParser.getOptions(Options.class);

    checkArgument(!options.inputJars.isEmpty(), "--input is required");
    checkArgument(options.output != null, "--output is required");
    checkArgument(!options.bootclasspath.isEmpty(), "--bootclasspath_entry is required");
    checkArgument(
        options.jdepsOutput == null || !Files.isDirectory(options.jdepsOutput),
        "Invalid value of --jdeps_output: '%s'",
        options.jdepsOutput);
    if (!options.fullClasspath.containsAll(options.directClasspath)) {
      ArrayList<Path> missing = Lists.newArrayList(options.directClasspath);
      missing.removeAll(options.fullClasspath);
      throw new IllegalArgumentException(
          "--strictdeps must be a subset of --classpath_entry but has additional entries: "
              + missing);
    }

    return options;
  }

  /** Validating converter for Paths. A Path is considered valid if it resolves to a file. */
  public static class PathConverter implements Converter<Path> {

    private final boolean mustExist;

    public PathConverter() {
      this.mustExist = false;
    }

    protected PathConverter(boolean mustExist) {
      this.mustExist = mustExist;
    }

    @Override
    public Path convert(String input) throws OptionsParsingException {
      try {
        Path path = FileSystems.getDefault().getPath(input);
        if (mustExist && !Files.exists(path)) {
          throw new OptionsParsingException(
              String.format("%s is not a valid path: it does not exist.", input));
        }
        return path;
      } catch (InvalidPathException e) {
        throw new OptionsParsingException(
            String.format("%s is not a valid path: %s.", input, e.getMessage()), e);
      }
    }

    @Override
    public String getTypeDescription() {
      return "a valid filesystem path";
    }
  }

  /**
   * Validating converter for Paths. A Path is considered valid if it resolves to a file and exists.
   */
  public static class ExistingPathConverter extends PathConverter {
    public ExistingPathConverter() {
      super(true);
    }
  }

  /** Converter for {@link CheckingMode} */
  public static class CheckingModeConverter extends EnumConverter<CheckingMode> {
    public CheckingModeConverter() {
      super(CheckingMode.class, "The checking mode for the dependency checker.");
    }
  }

  /**
   * The checking mode of the dependency checker.
   */
  public enum CheckingMode {
    /** Emit 'errors' on missing or incomplete dependencies. */
    ERROR,
    /** Emit 'warnings' on missing or incomplete dependencies. */
    WARNING,
    /**
     * Emit 'nothing' on missing or incomplete dependencies. This is mainly used to dump jdeps
     * protos.
     */
    SILENCE
  }
}
