// 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.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.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.MultimapBuilder;
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.Enumeration;
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 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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class JarScanner implements PluginContentScanner, AutoCloseable {
  private static final Logger log = LoggerFactory.getLogger(JarScanner.class);
  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);
    }

    Enumeration<JarEntry> e = jarFile.entries();
    while (e.hasMoreElements()) {
      JarEntry entry = e.nextElement();
      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) {
        log.warn(
            "Plugin {} has invalid class file {} inside of {}",
            pluginName,
            entry.getName(),
            jarFile.getName(),
            err);
        continue;
      }

      if (!Strings.isNullOrEmpty(def.annotationName)) {
        if (def.isConcrete()) {
          rawMap.put(def.annotationName, def);
        } else {
          log.warn(
              "Plugin {} tries to @{}(\"{}\") abstract class {}",
              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.<ClassData>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<>();
    Enumeration<JarEntry> e = jarFile.entries();
    while (e.hasMoreElements()) {
      JarEntry entry = e.nextElement();
      if (skip(entry)) {
        continue;
      }

      ClassData def = new ClassData(Collections.<String>emptySet());
      try {
        new ClassReader(read(jarFile, entry)).accept(def, SKIP_ALL);
      } catch (RuntimeException err) {
        log.warn("Jar {} has invalid class file {}", jarFile.getName(), entry.getName(), err);
        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.ASM5);
      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.ASM5);
    }

    @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 Enumeration<PluginEntry> entries() {
    return Collections.enumeration(
        Lists.transform(
            Collections.list(jarFile.entries()),
            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,
        new Maps.EntryTransformer<Object, Object, String>() {
          @Override
          public String transformEntry(Object key, Object value) {
            return (String) value;
          }
        });
  }
}
