// Copyright (C) 2014 The Android Open Source Project
//
// 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.gerrit.server.plugins;

import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.Iterables.transform;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.MultimapBuilder;
import com.google.common.flogger.FluentLogger;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.stream.Stream;
import org.eclipse.jgit.util.IO;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
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;
import org.objectweb.asm.Type;

public class JarScanner implements PluginContentScanner, AutoCloseable {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private static final int SKIP_ALL =
      ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES;
  private final JarFile jarFile;

  public JarScanner(Path src) throws IOException {
    this.jarFile = new JarFile(src.toFile());
  }

  @Override
  public Map<Class<? extends Annotation>, Iterable<ExtensionMetaData>> scan(
      String pluginName, Iterable<Class<? extends Annotation>> annotations)
      throws InvalidPluginException {
    Set<String> descriptors = new HashSet<>();
    ListMultimap<String, JarScanner.ClassData> rawMap =
        MultimapBuilder.hashKeys().arrayListValues().build();
    Map<Class<? extends Annotation>, String> classObjToClassDescr = new HashMap<>();

    for (Class<? extends Annotation> annotation : annotations) {
      String descriptor = Type.getType(annotation).getDescriptor();
      descriptors.add(descriptor);
      classObjToClassDescr.put(annotation, descriptor);
    }

    for (JarEntry entry : entriesOf(jarFile)) {
      if (skip(entry)) {
        continue;
      }

      ClassData def = new ClassData(descriptors);
      try {
        new ClassReader(read(jarFile, entry)).accept(def, SKIP_ALL);
      } catch (IOException err) {
        throw new InvalidPluginException("Cannot auto-register", err);
      } catch (RuntimeException err) {
        logger.atWarning().withCause(err).log(
            "Plugin %s has invalid class file %s inside of %s",
            pluginName, entry.getName(), jarFile.getName());
        continue;
      }

      if (!Strings.isNullOrEmpty(def.annotationName)) {
        if (def.isConcrete()) {
          rawMap.put(def.annotationName, def);
        } else {
          logger.atWarning().log(
              "Plugin %s tries to @%s(\"%s\") abstract class %s",
              pluginName, def.annotationName, def.annotationValue, def.className);
        }
      }
    }

    ImmutableMap.Builder<Class<? extends Annotation>, Iterable<ExtensionMetaData>> result =
        ImmutableMap.builder();

    for (Class<? extends Annotation> annotoation : annotations) {
      String descr = classObjToClassDescr.get(annotoation);
      Collection<ClassData> discoverdData = rawMap.get(descr);
      Collection<ClassData> values = firstNonNull(discoverdData, Collections.emptySet());

      result.put(
          annotoation,
          transform(values, cd -> new ExtensionMetaData(cd.className, cd.annotationValue)));
    }

    return result.build();
  }

  public List<String> findSubClassesOf(Class<?> superClass) throws IOException {
    return findSubClassesOf(superClass.getName());
  }

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

  private List<String> findSubClassesOf(String superClass) throws IOException {
    String name = superClass.replace('.', '/');

    List<String> classes = new ArrayList<>();
    for (JarEntry entry : entriesOf(jarFile)) {
      if (skip(entry)) {
        continue;
      }

      ClassData def = new ClassData(Collections.emptySet());
      try {
        new ClassReader(read(jarFile, entry)).accept(def, SKIP_ALL);
      } catch (RuntimeException err) {
        logger.atWarning().withCause(err).log(
            "Jar %s has invalid class file %s", jarFile.getName(), entry.getName());
        continue;
      }

      if (name.equals(def.superName)) {
        classes.addAll(findSubClassesOf(def.className));
        if (def.isConcrete()) {
          classes.add(def.className);
        }
      }
    }

    return classes;
  }

  private static boolean skip(JarEntry entry) {
    if (!entry.getName().endsWith(".class")) {
      return true; // Avoid non-class resources.
    }
    if (entry.getSize() <= 0) {
      return true; // Directories have 0 size.
    }
    if (entry.getSize() >= 1024 * 1024) {
      return true; // Do not scan huge class files.
    }
    return false;
  }

  private static byte[] read(JarFile jarFile, JarEntry entry) throws IOException {
    byte[] data = new byte[(int) entry.getSize()];
    try (InputStream in = jarFile.getInputStream(entry)) {
      IO.readFully(in, data, 0, data.length);
    }
    return data;
  }

  public static class ClassData extends ClassVisitor {
    int access;
    String className;
    String superName;
    String annotationName;
    String annotationValue;
    String[] interfaces;
    Collection<String> exports;

    private ClassData(Collection<String> exports) {
      super(Opcodes.ASM7);
      this.exports = exports;
    }

    boolean isConcrete() {
      return (access & Opcodes.ACC_ABSTRACT) == 0 && (access & Opcodes.ACC_INTERFACE) == 0;
    }

    @Override
    public void visit(
        int version,
        int access,
        String name,
        String signature,
        String superName,
        String[] interfaces) {
      this.className = Type.getObjectType(name).getClassName();
      this.access = access;
      this.superName = superName;
    }

    @Override
    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
      if (!visible) {
        return null;
      }
      Optional<String> found = exports.stream().filter(x -> x.equals(desc)).findAny();
      if (found.isPresent()) {
        annotationName = desc;
        return new AbstractAnnotationVisitor() {
          @Override
          public void visit(String name, Object value) {
            annotationValue = (String) value;
          }
        };
      }
      return null;
    }

    @Override
    public void visitSource(String arg0, String arg1) {}

    @Override
    public void visitOuterClass(String arg0, String arg1, String arg2) {}

    @Override
    public MethodVisitor visitMethod(
        int arg0, String arg1, String arg2, String arg3, String[] arg4) {
      return null;
    }

    @Override
    public void visitInnerClass(String arg0, String arg1, String arg2, int arg3) {}

    @Override
    public FieldVisitor visitField(int arg0, String arg1, String arg2, String arg3, Object arg4) {
      return null;
    }

    @Override
    public void visitEnd() {}

    @Override
    public void visitAttribute(Attribute arg0) {}
  }

  private abstract static class AbstractAnnotationVisitor extends AnnotationVisitor {
    AbstractAnnotationVisitor() {
      super(Opcodes.ASM7);
    }

    @Override
    public AnnotationVisitor visitAnnotation(String arg0, String arg1) {
      return null;
    }

    @Override
    public AnnotationVisitor visitArray(String arg0) {
      return null;
    }

    @Override
    public void visitEnum(String arg0, String arg1, String arg2) {}

    @Override
    public void visitEnd() {}
  }

  @Override
  public Optional<PluginEntry> getEntry(String resourcePath) throws IOException {
    JarEntry jarEntry = jarFile.getJarEntry(resourcePath);
    if (jarEntry == null || jarEntry.getSize() == 0) {
      return Optional.empty();
    }

    return Optional.of(resourceOf(jarEntry));
  }

  @Override
  public Stream<PluginEntry> entries() {
    return jarFile.stream()
        .map(
            jarEntry -> {
              try {
                return resourceOf(jarEntry);
              } catch (IOException e) {
                throw new IllegalArgumentException(
                    "Cannot convert jar entry " + jarEntry + " to a resource", e);
              }
            });
  }

  @Override
  public InputStream getInputStream(PluginEntry entry) throws IOException {
    return jarFile.getInputStream(jarFile.getEntry(entry.getName()));
  }

  @Override
  public Manifest getManifest() throws IOException {
    return jarFile.getManifest();
  }

  private PluginEntry resourceOf(JarEntry jarEntry) throws IOException {
    return new PluginEntry(
        jarEntry.getName(),
        jarEntry.getTime(),
        Optional.of(jarEntry.getSize()),
        attributesOf(jarEntry));
  }

  private Map<Object, String> attributesOf(JarEntry jarEntry) throws IOException {
    Attributes attributes = jarEntry.getAttributes();
    if (attributes == null) {
      return Collections.emptyMap();
    }
    return Maps.transformEntries(attributes, (key, value) -> (String) value);
  }

  private static Iterable<JarEntry> entriesOf(JarFile jarFile) {
    return jarFile.stream().collect(toImmutableList());
  }
}
