// 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 com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.importdeps.AbstractClassEntryState.IncompleteState;
import com.google.devtools.build.importdeps.ResultCollector.MissingMember;
import com.google.devtools.build.lib.view.proto.Deps.Dependencies;
import com.google.devtools.build.lib.view.proto.Deps.Dependency;
import com.google.devtools.build.lib.view.proto.Deps.Dependency.Kind;
import java.io.Closeable;
import java.io.IOError;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.nio.file.Path;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.zip.ZipFile;
import javax.annotation.Nullable;
import org.objectweb.asm.ClassReader;

/**
 * Checker that checks the classes in the input jars have complete dependencies. If not, output the
 * missing dependencies to a file.
 */
public final class ImportDepsChecker implements Closeable {

  private final ClassCache classCache;
  private final ResultCollector resultCollector;
  private final ImmutableSet<Path> inputJars;

  public ImportDepsChecker(
      ImmutableSet<Path> bootclasspath,
      ImmutableSet<Path> directClasspath,
      ImmutableSet<Path> classpath,
      ImmutableSet<Path> inputJars,
      boolean checkMissingMembers)
      throws IOException {
    this.classCache =
        new ClassCache(
            bootclasspath,
            directClasspath,
            classpath,
            inputJars,
            /*populateMembers=*/ checkMissingMembers);
    this.resultCollector = new ResultCollector(checkMissingMembers);
    this.inputJars = inputJars;
  }

  /**
   * Checks for dependency problems in the given input jars against the classpath.
   *
   * @return {@literal true} for no problems, {@literal false} otherwise.
   */
  public boolean check() throws IOException {
    for (Path path : inputJars) {
      try (ZipFile jarFile = new ZipFile(path.toFile())) {
        jarFile.stream()
            .forEach(
                entry -> {
                  String name = entry.getName();
                  if (!name.endsWith(".class") || name.startsWith("META-INF/versions/")) {
                    // Ignore META-INF/versions/ since given bootclasspath may not cover them, and
                    // any classes would usually only differ in using newer language features.
                    return;
                  }
                  try (InputStream inputStream = jarFile.getInputStream(entry)) {
                    ClassReader reader = new ClassReader(inputStream);
                    DepsCheckerClassVisitor checker =
                        new DepsCheckerClassVisitor(classCache, resultCollector);
                    reader.accept(checker, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
                  } catch (IOException e) {
                    throw new IOError(e);
                  } catch (RuntimeException e) {
                    System.err.printf(
                        "A runtime exception occurred when processing the class %s "
                            + "in the zip file %s\n",
                        name, path);
                    throw e;
                  }
                });
      }
    }
    return resultCollector.isEmpty();
  }

  /** Emit the jdeps proto. The parameter ruleLabel is optional, indicated with the empty string. */
  public Dependencies emitJdepsProto(String ruleLabel) {
    Dependencies.Builder builder = Dependencies.newBuilder();
    ImmutableMap<Path, Boolean> paths = classCache.collectUsedJarsInRegularClasspath();
    paths.forEach(
        (path, explicit) ->
            builder.addDependency(
                Dependency.newBuilder()
                    .setKind(explicit ? Kind.EXPLICIT : Kind.IMPLICIT)
                    .setPath(path.toString())
                    .build()));
    return builder.setRuleLabel(ruleLabel).setSuccess(true).build();
  }

  private static final String INDENT = "    ";

  public String computeResultOutput(String ruleLabel) {
    StringBuilder builder = new StringBuilder();
    ImmutableList<String> missingClasses = resultCollector.getSortedMissingClassInternalNames();
    outputMissingClasses(builder, missingClasses);

    ImmutableList<IncompleteState> incompleteClasses = resultCollector.getSortedIncompleteClasses();
    outputIncompleteClasses(builder, incompleteClasses);

    ImmutableList<MissingMember> missingMembers = resultCollector.getSortedMissingMembers();
    outputMissingMembers(builder, missingMembers);

    outputStatistics(builder, missingClasses, incompleteClasses, missingMembers);

    emitAddDepCommandForIndirectJars(ruleLabel, builder);
    return builder.toString();
  }

  private void emitAddDepCommandForIndirectJars(String ruleLabel, StringBuilder builder) {
    ImmutableMultimap<Path, String> indirectJars = resultCollector.getSortedIndirectDeps();
    if (!indirectJars.isEmpty()) {
      Set<String> labels = new LinkedHashSet<>();
      for (var e : indirectJars.asMap().entrySet()) {
        Path jar = e.getKey();
        String label = extractLabel(jar);
        builder.append("Indirect reference to classes from ");
        if (label != null) {
          labels.add(label);
          builder.append(label);
        } else {
          builder.append(jar);
        }
        builder.append(" in:");
        for (String missing : e.getValue()) {
          builder.append('\n').append(INDENT).append(missing.replace('/', '.'));
        }
        builder.append('\n');
      }
      if (ruleLabel.isEmpty() || labels.isEmpty()) {
        builder
            .append(
                "*** Missing strict dependencies on the following Jars which don't carry "
                    + "rule labels.\nPlease determine the originating rules, e.g., using Bazel's "
                    + "'query' command, and add them to the dependencies of ")
            .append(ruleLabel.isEmpty() ? inputJars : ruleLabel)
            .append('\n');
        for (Path jar : indirectJars.keySet()) {
          builder.append(jar).append('\n');
        }
      } else {
        builder.append("*** Command to add missing strict dependencies: ***\n\n");
        builder.append("    add_dep ");
        for (String indirectLabel : labels) {
          builder.append(indirectLabel).append(" ");
        }
        builder.append(ruleLabel).append('\n');
      }
    }
  }

  private void outputStatistics(
      StringBuilder builder,
      ImmutableList<String> missingClasses,
      ImmutableList<IncompleteState> incompleteClasses,
      ImmutableList<MissingMember> missingMembers) {
    if (missingClasses.size() + incompleteClasses.size() + missingMembers.size() != 0) {
      builder
          .append("===Total===\n")
          .append("missing=")
          .append(missingClasses.size())
          .append('\n')
          .append("incomplete=")
          .append(incompleteClasses.size())
          .append('\n')
          .append("missing_members=")
          .append(missingMembers.size())
          .append('\n');
    }
  }

  private void outputMissingMembers(
      StringBuilder builder, ImmutableList<MissingMember> missingMembers) {
    LinkedHashSet<ClassInfo> classesWithMissingMembers = new LinkedHashSet<>();
    for (MissingMember missing : missingMembers) {
      builder
          .append("Missing member '")
          .append(missing.memberName())
          .append("' in class ")
          .append(missing.owner().internalName().replace('/', '.'))
          .append(" : name=")
          .append(missing.memberName())
          .append(", descriptor=")
          .append(missing.descriptor())
          .append('\n');
      classesWithMissingMembers.add(missing.owner());
    }
    if (!classesWithMissingMembers.isEmpty()) {
      builder.append("The class hierarchies of the classes with missing members:").append("\n");
      classesWithMissingMembers.forEach(
          missingClass -> printClassHierarchy(missingClass, builder, "    "));
    }
  }

  private static void printClassHierarchy(
      ClassInfo klass,
      StringBuilder builder,
      String indent) {
    builder.append(indent).append(toLabeledClassName(klass)).append('\n');
    String superIndent = indent + "    ";

    for (ClassInfo superClass : klass.superClasses()) {
      printClassHierarchy(superClass, builder, superIndent);
    }
  }

  private void outputIncompleteClasses(
      StringBuilder builder, ImmutableList<IncompleteState> incompleteClasses) {
    HashMultimap<String, ClassInfo> map = HashMultimap.create();
    for (IncompleteState incomplete : incompleteClasses) {
      ResolutionFailureChain chain = incomplete.resolutionFailureChain();
      map.putAll(chain.getMissingClassesWithSubclasses());
    }
    map.asMap().entrySet().stream()
        .sorted(Map.Entry.comparingByKey())
        .forEach(
            entry -> {
              builder
                  .append("Indirectly missing class ")
                  .append(entry.getKey().replace('/', '.'))
                  .append(". Referenced by:")
                  .append('\n');
              entry.getValue().stream()
                  .distinct()
                  .sorted()
                  .forEach(
                      reference -> {
                        builder.append(INDENT).append(toLabeledClassName(reference)).append('\n');
                      });
            });
  }

  private void outputMissingClasses(StringBuilder builder, ImmutableList<String> missingClasses) {
    for (String missing : missingClasses) {
      builder.append("Missing ").append(missing.replace('/', '.')).append('\n');
    }
  }

  private static final String toLabeledClassName(ClassInfo klass) {
    String klassName = klass.internalName().replace('/', '.');
    String targetName = extractLabel(klass.jarPath());
    if (targetName != null) {
      int index = targetName.lastIndexOf('/');
      if (index >= 0) {
        // Just print the target name without the full path, as the Bazel tests have
        // different full paths of targets.
        targetName = targetName.substring(index + 1);
      }
      return klassName + " (in " + targetName + ")";
    } else {
      return klassName;
    }
  }

  private static final Attributes.Name TARGET_LABEL = new Attributes.Name("Target-Label");
  private static final Attributes.Name INJECTING_RULE_KIND =
      new Attributes.Name("Injecting-Rule-Kind");

  @Nullable
  private static String extractLabel(Path jarPath) {
    try (JarFile jar = new JarFile(jarPath.toFile())) {
      Manifest manifest = jar.getManifest();
      if (manifest == null) {
        return null;
      }
      Attributes attributes = manifest.getMainAttributes();
      if (attributes == null) {
        return null;
      }
      String targetLabel = (String) attributes.get(TARGET_LABEL);
      String injectingRuleKind = (String) attributes.get(INJECTING_RULE_KIND);
      if (injectingRuleKind == null) {
        return targetLabel;
      } else {
        return String.format("\"%s %s\"", targetLabel, injectingRuleKind);
      }
    } catch (IOException e) {
      throw new UncheckedIOException(e);
    }
  }

  @Override
  public void close() throws IOException {
    classCache.close();
  }
}
