// 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.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.MoreObjects;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.Closer;
import com.google.devtools.build.importdeps.AbstractClassEntryState.ExistingState;
import com.google.devtools.build.importdeps.AbstractClassEntryState.IncompleteState;
import com.google.devtools.build.importdeps.AbstractClassEntryState.MissingState;
import com.google.devtools.build.importdeps.ClassInfo.MemberInfo;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import javax.annotation.Nullable;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

/** A cache that stores all the accessible classes in a set of JARs. */
public final class ClassCache implements Closeable {

  private final LazyClasspath lazyClasspath;
  private boolean isClosed;

  public ClassCache(
      ImmutableList<Path> bootclasspath,
      ImmutableList<Path> directClasspath,
      ImmutableList<Path> regularClasspath,
      ImmutableList<Path> inputJars)
      throws IOException {
    lazyClasspath = new LazyClasspath(bootclasspath, directClasspath, regularClasspath, inputJars);
  }

  public AbstractClassEntryState getClassState(String internalName) {
    checkState(!isClosed, "The cache has been closed.");
    LazyClassEntry entry = lazyClasspath.getLazyEntry(internalName);
    if (entry == null) {
      return MissingState.singleton();
    }
    return entry.getState(lazyClasspath);
  }

  public ImmutableList<Path> collectUsedJarsInRegularClasspath() {
    return lazyClasspath.collectUsedJarsInRegularClasspath();
  }

  @Override
  public void close() throws IOException {
    lazyClasspath.close();
    isClosed = true;
  }

  static class LazyClassEntry {
    private final String internalName;
    private final ZipFile zipFile;
    private final Path jarPath;
    private final boolean direct;

    /**
     * The state of this class entry. If {@literal null}, then this class has not been resolved yet.
     */
    @Nullable private AbstractClassEntryState state = null;

    private LazyClassEntry(String internalName, ZipFile zipFile, Path jarPath, boolean direct) {
      this.internalName = internalName;
      this.zipFile = zipFile;
      this.jarPath = jarPath;
      this.direct = direct;
    }

    ZipFile getZipFile() {
      return zipFile;
    }

    @Nullable
    public AbstractClassEntryState getState(LazyClasspath classpath) {
      resolveIfNot(classpath);
      checkState(
          state != null && !state.isMissingState(),
          "The state cannot be null or MISSING. %s",
          state);
      return state;
    }

    @Override
    public String toString() {
      return MoreObjects.toStringHelper(this)
          .add("internalName", internalName)
          .add("state", state)
          .toString();
    }

    boolean isResolved() {
      return state != null;
    }

    private void resolveIfNot(LazyClasspath lazyClasspath) {
      if (isResolved()) {
        return;
      }
      resolveClassEntry(this, lazyClasspath);
      checkNotNull(state, "After resolution, the state cannot be null");
    }

    private static void resolveClassEntry(LazyClassEntry classEntry, LazyClasspath lazyClasspath) {
      if (classEntry.state != null) {
        // Already resolved. See if it is the existing state.
        return;
      }

      String entryName = classEntry.internalName + ".class";
      ZipEntry zipEntry =
          checkNotNull(
              classEntry.zipFile.getEntry(entryName), "The zip entry %s is null.", entryName);
      try (InputStream inputStream = classEntry.zipFile.getInputStream(zipEntry)) {
        ClassReader classReader = new ClassReader(inputStream);
        ImmutableList.Builder<ResolutionFailureChain> resolutionFailureChainsBuilder =
            ImmutableList.builder();
        for (String superName :
            combineWithoutNull(classReader.getSuperName(), classReader.getInterfaces())) {
          Optional<ResolutionFailureChain> failurePath =
              resolveSuperClassEntry(superName, lazyClasspath);
          failurePath.map(resolutionFailureChainsBuilder::add);
        }
        ClassInfoBuilder classInfoBuilder =
            new ClassInfoBuilder().setJarPath(classEntry.jarPath).setDirect(classEntry.direct);
        classReader.accept(classInfoBuilder, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);

        ImmutableList<ResolutionFailureChain> resolutionFailureChains =
            resolutionFailureChainsBuilder.build();
        if (resolutionFailureChains.isEmpty()) {
          classEntry.state =
              ExistingState.create(classInfoBuilder.build(lazyClasspath, /*incomplete=*/ false));
        } else {
          ClassInfo classInfo = classInfoBuilder.build(lazyClasspath, /*incomplete=*/ true);
          classEntry.state =
              IncompleteState.create(
                  classInfo,
                  ResolutionFailureChain.createWithParent(classInfo, resolutionFailureChains));
        }
      } catch (IOException e) {
        throw new RuntimeException("Error when resolving class entry " + entryName, e);
      } catch (RuntimeException e) {
        System.err.println(
            "A runtime exception occurred. The following is the content in the class index. "
                + e.getMessage());
        lazyClasspath.printClasspath(System.err);
        throw e;
      }
    }

    private static Optional<ResolutionFailureChain> resolveSuperClassEntry(
        String superName, LazyClasspath lazyClasspath) {
      LazyClassEntry superClassEntry = lazyClasspath.getLazyEntry(superName);

      if (superClassEntry == null) {
        return Optional.of(ResolutionFailureChain.createMissingClass(superName));
      } else {
        resolveClassEntry(superClassEntry, lazyClasspath);
        AbstractClassEntryState superState = superClassEntry.state;
        if (superState instanceof ExistingState) {
          // Do nothing. Good to proceed.
          return Optional.empty();
        } else if (superState instanceof IncompleteState) {
          return Optional.of(superState.asIncompleteState().resolutionFailureChain());
        } else {
          throw new RuntimeException("Cannot reach here. superState is " + superState);
        }
      }
    }
  }

  private static ImmutableList<String> combineWithoutNull(
      @Nullable String first, @Nullable String[] others) {
    ImmutableList.Builder<String> list = ImmutableList.builder();
    if (first != null) {
      list.add(first);
    }
    if (others != null) {
      list.add(others);
    }
    return list.build();
  }

  /** The classpath, emulating the behavior of the real classpath. */
  @VisibleForTesting
  static final class LazyClasspath implements Closeable {
    private final ClassIndex bootclasspath;
    private final ClassIndex regularClasspath;
    private final ClassIndex inputJars;
    private final ImmutableList<ClassIndex> orderedClasspath;
    private final Closer closer = Closer.create();

    public LazyClasspath(
        ImmutableList<Path> bootclasspath,
        ImmutableList<Path> directClasspath,
        ImmutableList<Path> regularClasspath,
        ImmutableList<Path> inputJars)
        throws IOException {
      checkArgument(
          regularClasspath.containsAll(directClasspath),
          "Some direct deps %s missing from transitive deps %s",
          directClasspath,
          regularClasspath);
      this.bootclasspath = new ClassIndex("boot classpath", bootclasspath, Predicates.alwaysTrue());
      this.inputJars = new ClassIndex("input jars", inputJars, Predicates.alwaysTrue());
      this.regularClasspath =
          new ClassIndex(
              "regular classpath",
              regularClasspath,
              jar ->
                  bootclasspath.contains(jar)
                      || inputJars.contains(jar)
                      || directClasspath.contains(jar));
      // Reflect runtime resolution order, with input before classpath similar to javac
      this.orderedClasspath =
          ImmutableList.of(this.bootclasspath, this.inputJars, this.regularClasspath);
      this.orderedClasspath.forEach(closer::register);
    }

    public LazyClassEntry getLazyEntry(String internalName) {
      return orderedClasspath
          .stream()
          .map(classIndex -> classIndex.getClassEntry(internalName))
          .filter(Objects::nonNull)
          .findFirst()
          .orElse(null);
    }

    public ImmutableList<Path> collectUsedJarsInRegularClasspath() {
      return regularClasspath.collectUsedJarFiles();
    }

    public void printClasspath(PrintStream stream) {
      orderedClasspath.forEach(c -> c.printClasspath(stream));
    }

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

  /**
   * Representation of a class path, composed of a list of JARs. It indexes all the class files with
   * the class names.
   */
  private static final class ClassIndex implements Closeable {

    private final String name;
    private final ImmutableMap<String, LazyClassEntry> classIndex;
    private final Closer closer;

    public ClassIndex(String name, ImmutableList<Path> jarFiles, Predicate<Path> isDirect)
        throws IOException {
      this.name = name;
      this.closer = Closer.create();
      classIndex = buildClassIndex(jarFiles, closer, isDirect);
    }

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

    public LazyClassEntry getClassEntry(String internalName) {
      return classIndex.get(internalName);
    }

    public ImmutableList<Path> collectUsedJarFiles() {
      HashSet<Path> usedJars = new HashSet<>();
      for (Map.Entry<String, LazyClassEntry> entry : classIndex.entrySet()) {
        LazyClassEntry clazz = entry.getValue();
        if (clazz.isResolved()) {
          usedJars.add(clazz.jarPath);
        }
      }
      return ImmutableList.sortedCopyOf(usedJars);
    }

    private void printClasspath(PrintStream stream) {
      stream.println("Classpath: " + name);
      int counter = 0;
      for (Map.Entry<String, LazyClassEntry> entry : classIndex.entrySet()) {
        stream.printf("%d  %s\n    %s\n\n", ++counter, entry.getKey(), entry.getValue());
      }
    }

    private static ImmutableMap<String, LazyClassEntry> buildClassIndex(
        ImmutableList<Path> jars, Closer closer, Predicate<Path> isDirect) throws IOException {
      HashMap<String, LazyClassEntry> result = new HashMap<>();
      for (Path jarPath : jars) {
        boolean jarIsDirect = isDirect.test(jarPath);
        try {
          ZipFile zipFile = closer.register(new ZipFile(jarPath.toFile()));
          zipFile
              .stream()
              .forEach(
                  entry -> {
                    String name = entry.getName();
                    if (!name.endsWith(".class")) {
                      return; // Not a class file.
                    }
                    String internalName = name.substring(0, name.lastIndexOf('.'));
                    result.computeIfAbsent(
                        internalName,
                        key -> new LazyClassEntry(key, zipFile, jarPath, jarIsDirect));
                  });
        } catch (Throwable e) {
          throw new RuntimeException("Error in reading zip file " + jarPath, e);
        }
      }
      return ImmutableMap.copyOf(result);
    }
  }

  /** Builder to build a ClassInfo object from the class file. */
  private static class ClassInfoBuilder extends ClassVisitor {

    private String internalName;
    private final ImmutableSet.Builder<MemberInfo> members = ImmutableSet.builder();
    private ImmutableList<String> superClasses;
    private Path jarPath;
    private boolean directDep;

    public ClassInfoBuilder() {
      super(Opcodes.ASM7);
    }

    @Override
    public void visit(
        int version,
        int access,
        String name,
        String signature,
        String superName,
        String[] interfaces) {
      checkState(internalName == null && superClasses == null, "This visitor is already used.");
      internalName = name;
      superClasses = combineWithoutNull(superName, interfaces);
    }

    @Override
    public FieldVisitor visitField(
        int access, String name, String desc, String signature, Object value) {
      members.add(MemberInfo.create(name, desc));
      return null;
    }

    @Override
    public MethodVisitor visitMethod(
        int access, String name, String desc, String signature, String[] exceptions) {
      members.add(MemberInfo.create(name, desc));
      return null;
    }

    public ClassInfoBuilder setJarPath(Path jarPath) {
      this.jarPath = jarPath;
      return this;
    }

    public ClassInfoBuilder setDirect(boolean direct) {
      this.directDep = direct;
      return this;
    }

    public ClassInfo build(LazyClasspath lazyClasspath, boolean incomplete) {
      ImmutableList<ClassInfo> superClassInfos =
          superClasses
              .stream()
              .map(lazyClasspath::getLazyEntry)
              // nulls possible when building ClassInfo for an "incomplete" class
              .filter(entry -> entry != null && entry.state != null)
              .map(entry -> entry.state.classInfo().get())
              .collect(ImmutableList.toImmutableList());
      checkState(
          incomplete || superClassInfos.size() == superClasses.size(),
          "Missing class info for some of %s's super types %s: %s",
          internalName,
          superClasses,
          superClassInfos);
      return ClassInfo.create(
          checkNotNull(internalName),
          checkNotNull(jarPath),
          directDep,
          superClassInfos,
          members.build());
    }
  }
}
