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

public class JarScanner implements PluginContentScanner, AutoCloseable {
  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) {
        PluginLoader.log.warn(String.format(
            "Plugin %s has invalid class file %s inside of %s", pluginName,
            entry.getName(), jarFile.getName()), err);
        continue;
      }

      if (!Strings.isNullOrEmpty(def.annotationName)) {
        if (def.isConcrete()) {
            rawMap.put(def.annotationName, def);
        } else {
          PluginLoader.log.warn(String.format(
              "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.<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) {
        PluginLoader.log.warn(String.format("Jar %s has invalid class file %s",
            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;
          }
        });
  }
}
