// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.jasmin;

import static com.android.tools.r8.utils.DescriptorUtils.getPathFromDescriptor;

import com.android.tools.r8.ByteDataView;
import com.android.tools.r8.ClassFileConsumer;
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.dex.ApplicationReader;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.naming.MemberNaming.FieldSignature;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.origin.PathOrigin;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.StringUtils.BraceType;
import com.android.tools.r8.utils.Timing;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import jasmin.ClassFile;
import java.io.ByteArrayOutputStream;
import java.io.StringReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class JasminBuilder {

  public enum ClassFileVersion {
    JDK_1_1 {
      @Override
      public int getMajorVersion() {
        return 45;
      }

      @Override
      public int getMinorVersion() {
        return 3;
      }
    },
    JDK_1_2 {
      @Override
      public int getMajorVersion() {
        return 46;
      }
    },
    JDK_1_3 {
      @Override
      public int getMajorVersion() {
        return 47;
      }
    },
    JDK_1_4 {
      @Override
      public int getMajorVersion() {
        return 48;
      }
    },
    /** JSE 5 is not fully supported by Jasmin. Interfaces will not work. */
    JSE_5 {
      @Override
      public int getMajorVersion() {
        return 49;
      }
    };

    public abstract int getMajorVersion();

    public int getMinorVersion() {
      return 0;
    }
  }

  public class ClassBuilder {
    public final String name;
    public final String superName;
    public final ImmutableList<String> interfaces;
    private final List<String> methods = new ArrayList<>();
    private final List<String> fields = new ArrayList<>();
    private boolean makeInit = false;
    private boolean hasInit = false;
    private final List<String> clinit = new ArrayList<>();
    private boolean isAbstract = false;
    private boolean isInterface = false;
    private String access = "public";

    private ClassBuilder(String name) {
      this(name, "java/lang/Object");
    }

    private ClassBuilder(String name, String superName) {
      this(name , superName, new String[0]);
    }

    private ClassBuilder(String name, String superName, String... interfaces) {
      this.name = name;
      this.superName = superName;
      this.interfaces = ImmutableList.copyOf(interfaces);
    }

    public String getSourceFile() {
      return name + ".j";
    }

    public String getDescriptor() {
      return "L" + name + ";";
    }

    public MethodSignature addAbstractMethod(
        String name,
        List<String> argumentTypes,
        String returnType) {
      return addMethod("public abstract", name, argumentTypes, returnType);
    }

    public MethodSignature addFinalMethod(
        String name,
        List<String> argumentTypes,
        String returnType,
        String... lines) {
      makeInit = true;
      return addMethod("public final", name, argumentTypes, returnType, lines);
    }

    public MethodSignature addVirtualMethod(String name, String returnType, String... lines) {
      return addVirtualMethod(name, ImmutableList.of(), returnType, lines);
    }

    public MethodSignature addVirtualMethod(
        String name,
        List<String> argumentTypes,
        String returnType,
        String... lines) {
      makeInit = true;
      return addMethod("public", name, argumentTypes, returnType, lines);
    }

    /**
     * Note that the JVM rejects native methods with code. This method is used to test that D8
     * removes code from native methods.
     */
    public MethodSignature addNativeMethodWithCode(
        String name,
        List<String> argumentTypes,
        String returnType,
        String... lines) {
      makeInit = true;
      return addMethod("public static native", name, argumentTypes, returnType, lines);
    }

    public MethodSignature addBridgeMethod(
        String name,
        List<String> argumentTypes,
        String returnType,
        String... lines) {
      makeInit = true;
      return addMethod("public bridge", name, argumentTypes, returnType, lines);
    }

    public MethodSignature addPrivateVirtualMethod(
        String name,
        List<String> argumentTypes,
        String returnType,
        String... lines) {
      makeInit = true;
      return addMethod("private", name, argumentTypes, returnType, lines);
    }

    public MethodSignature addStaticMethod(
        String name,
        List<String> argumentTypes,
        String returnType,
        String... lines) {
      return addMethod("public static", name, argumentTypes, returnType, lines);
    }

    public MethodBuilder staticMethodBuilder(
        String name, List<String> argumentTypes, String returnType) {
      return new MethodBuilder(name, argumentTypes, returnType, this).setPublic().setStatic();
    }

    public MethodSignature addPackagePrivateStaticMethod(
        String name,
        List<String> argumentTypes,
        String returnType,
        String... lines) {
      return addMethod("static", name, argumentTypes, returnType, lines);
    }

    public MethodSignature addMainMethod(Iterable<String> lines) {
      return addMainMethod(Iterables.toArray(lines, String.class));
    }

    public MethodSignature addMainMethod(String... lines) {
      return addStaticMethod("main", ImmutableList.of("[Ljava/lang/String;"), "V", lines);
    }

    public MethodSignature addMethod(
        String access,
        String name,
        List<String> argumentTypes,
        String returnType,
        String... lines) {
      StringBuilder builder = new StringBuilder();
      builder
          .append(".method ")
          .append(access)
          .append(" ")
          .append(name)
          .append(StringUtils.join("", argumentTypes, BraceType.PARENS))
          .append(returnType)
          .append("\n");
      for (String line : lines) {
        builder.append(line).append("\n");
      }
      builder.append(".end method\n");
      methods.add(builder.toString());

      String returnJavaType = DescriptorUtils.descriptorToJavaType(returnType);
      String[] argumentJavaTypes = new String[argumentTypes.size()];
      for (int i = 0; i < argumentTypes.size(); i++) {
        argumentJavaTypes[i] = DescriptorUtils.descriptorToJavaType(argumentTypes.get(i));
      }
      return new MethodSignature(name, returnJavaType, argumentJavaTypes);
    }

    public void addClassInitializer(String... lines) {
      clinit.addAll(Arrays.asList(lines));
    }

    public FieldSignature addField(String flags, String name, String type, String value) {
      fields.add(
          ".field " + flags + " " + name + " " + type + (value != null ? (" = " + value) : ""));
      return new FieldSignature(name, type);
    }

    public FieldSignature addStaticField(String name, String type) {
      return addStaticField(name, type, null);
    }

    public FieldSignature addStaticField(String name, String type, String value) {
      return addField("public static", name, type, value);
    }

    public FieldSignature addStaticFinalField(String name, String type, String value) {
      return addField("public static final", name, type, value);
    }

    @Override
    public String toString() {
      StringBuilder builder = new StringBuilder();
      builder.append(".bytecode ").append(majorVersion).append('.').append(minorVersion)
          .append('\n');
      builder.append(".source ").append(getSourceFile()).append('\n');
      builder.append(".class");
      if (isAbstract) {
        builder.append(" abstract");
      } else if (isInterface) {
        builder.append(" interface abstract");
      }
      builder.append(" ").append(access).append(" ").append(name).append('\n');
      builder.append(".super ").append(superName).append('\n');
      for (String iface : interfaces) {
        builder.append(".implements ").append(iface).append('\n');
      }
      if (makeInit && !hasInit) {
        builder
            .append(".method public <init>()V\n")
            .append(".limit locals 1\n")
            .append(".limit stack 1\n")
            .append("  aload 0\n")
            .append("  invokespecial ").append(superName).append("/<init>()V\n")
            .append("  return\n")
            .append(".end method\n");
      }
      for (String field : fields) {
        builder.append(field).append("\n");
      }
      for (String method : methods) {
        builder.append(method).append("\n");
      }
      if (!clinit.isEmpty()) {
        builder.append(".method public static <clinit>()V\n");
        clinit.forEach(line -> builder.append(line).append('\n'));
        builder.append(".end method\n");
      }
      return builder.toString();
    }

    public void setIsAbstract() {
      isAbstract = true;
    }

    public void setIsInterface() {
      isInterface = true;
    }

    public void setAccess(String access) {
      this.access = access;
    }

    public MethodSignature addDefaultConstructor() {
      assert !hasInit;
      hasInit = true;
      return addMethod("public", "<init>", Collections.emptyList(), "V",
          ".limit stack 1",
          ".limit locals 1",
          "  aload_0",
          "  invokenonvirtual " + superName + "/<init>()V",
          "  return");
    }
  }

  public class MethodBuilder {

    private final String name;
    private final List<String> argumentTypes;
    private final String returnType;

    private final ClassBuilder parent;

    private List<String> instructions = new ArrayList<>();
    private int localsLimit = -1;
    private int stackLimit = -1;

    private boolean isPublic = false;
    private boolean isStatic = false;

    public MethodBuilder(
        String name, List<String> argumentTypes, String returnType, ClassBuilder parent) {
      this.name = name;
      this.argumentTypes = argumentTypes;
      this.returnType = returnType;
      this.parent = parent;
    }

    public MethodBuilder setPublic() {
      isPublic = true;
      return this;
    }

    public MethodBuilder setStatic() {
      isStatic = true;
      return this;
    }

    public MethodBuilder setCode(String... lines) {
      assert Arrays.stream(lines).noneMatch(line -> line.contains(".limit"));
      instructions.addAll(Arrays.asList(lines));
      return this;
    }

    public MethodBuilder setLocalsLimit(int localsLimit) {
      assert this.localsLimit < 0;
      this.localsLimit = localsLimit;
      return this;
    }

    public MethodBuilder setStackLimit(int stackLimit) {
      assert this.stackLimit < 0;
      this.stackLimit = stackLimit;
      return this;
    }

    public void build() {
      if (localsLimit < 0 || stackLimit < 0) {
        inferConservativeLimits();
      }
      StringBuilder builder = new StringBuilder();
      builder.append(".method ");
      if (isPublic) {
        builder.append("public ");
      }
      if (isStatic) {
        builder.append("static ");
      }
      builder
          .append(name)
          .append(StringUtils.join("", argumentTypes, BraceType.PARENS))
          .append(returnType)
          .append(System.lineSeparator());
      builder.append(".limit locals ").append(localsLimit).append(System.lineSeparator());
      builder.append(".limit stack ").append(stackLimit).append(System.lineSeparator());
      for (String line : instructions) {
        builder.append(line).append(System.lineSeparator());
      }
      builder.append(".end method").append(System.lineSeparator());
      parent.methods.add(builder.toString());
    }

    private void inferConservativeLimits() {
      int conservativeLimit = instructions.size() + argumentTypes.size();
      if (localsLimit < 0) {
        setLocalsLimit(conservativeLimit);
      }
      if (stackLimit < 0) {
        setStackLimit(conservativeLimit);
      }
    }
  }

  private final List<ClassBuilder> classes = new ArrayList<>();
  private final int minorVersion;
  private final int majorVersion;

  public JasminBuilder() {
    this(ClassFileVersion.JDK_1_4);
  }

  public JasminBuilder(ClassFileVersion version) {
    majorVersion = version.getMajorVersion();
    minorVersion = version.getMinorVersion();
  }

  public ClassBuilder addClass(String name) {
    ClassBuilder builder = new ClassBuilder(name);
    classes.add(builder);
    return builder;
  }

  public ClassBuilder addClass(String name, String superName) {
    ClassBuilder builder = new ClassBuilder(name, superName);
    classes.add(builder);
    return builder;
  }

  public ClassBuilder addClass(String name, String superName, String... interfaces) {
    ClassBuilder builder = new ClassBuilder(name, superName, interfaces);
    classes.add(builder);
    return builder;
  }

  public ClassBuilder addInterface(String name, String... interfaces) {
    // Interfaces are broken in Jasmin (the ACC_SUPER access flag is set) and the JSE_5 and later
    // will not load corresponding classes.
    assert majorVersion <= ClassFileVersion.JDK_1_4.getMajorVersion();
    ClassBuilder builder = new ClassBuilder(name, "java/lang/Object", interfaces);
    builder.setIsInterface();
    classes.add(builder);
    return builder;
  }

  public ImmutableList<ClassBuilder> getClasses() {
    return ImmutableList.copyOf(classes);
  }

  private static byte[] compile(ClassBuilder builder) throws Exception {
    ClassFile file = new ClassFile();
    file.readJasmin(new StringReader(builder.toString()), builder.name, false);
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    file.write(out);
    // Jasmin incorrectly sets super on interfaces: https://sourceforge.net/p/jasmin/bugs/5/
    return TestBase.transformer(
            out.toByteArray(), Reference.classFromBinaryName(file.getClassName()))
        .setAccessFlags(
            flags -> {
              if (flags.isInterface()) {
                flags.unsetSuper();
              }
            })
        .transform();
  }

  public ImmutableList.Builder<byte[]> buildClasses(ImmutableList.Builder<byte[]> builder)
      throws Exception {
    for (ClassBuilder clazz : classes) {
      builder.add(compile(clazz));
    }
    return builder;
  }

  public List<byte[]> buildClasses() throws Exception {
    return buildClasses(ImmutableList.builder()).build();
  }

  public AndroidApp build() throws Exception {
    Origin root = new PathOrigin(Paths.get("JasminBuilder"));
    AndroidApp.Builder builder = AndroidApp.builder();
    for (ClassBuilder clazz : classes) {
      Origin origin = new Origin(root) {
        @Override
        public String part() {
          return clazz.getSourceFile();
        }
      };
      builder.addClassProgramData(
          compile(clazz), origin, Collections.singleton(clazz.getDescriptor()));
    }
    return builder.build();
  }

  public List<Path> writeClassFiles(Path output) throws Exception {
    List<Path> outputs = new ArrayList<>(classes.size());
    for (ClassBuilder clazz : classes) {
      Path path = output.resolve(getPathFromDescriptor(clazz.getDescriptor()));
      Files.createDirectories(path.getParent());
      Files.write(path, compile(clazz));
      outputs.add(path);
    }
    return outputs;
  }

  public void writeClassFiles(ClassFileConsumer consumer, DiagnosticsHandler handler)
      throws Exception {
    for (ClassBuilder clazz : classes) {
      consumer.accept(ByteDataView.of(compile(clazz)), clazz.getDescriptor(), handler);
    }
  }

  public void writeJar(Path output) throws Exception {
    writeJar(output, null);
  }

  public void writeJar(Path output, DiagnosticsHandler handler) throws Exception {
    ClassFileConsumer consumer = new ClassFileConsumer.ArchiveConsumer(output);
    writeClassFiles(consumer, handler);
    consumer.finished(handler);
  }

  public DexApplication read() throws Exception {
    return read(new InternalOptions());
  }

  public DexApplication read(InternalOptions options) throws Exception {
    Timing timing = Timing.empty();
    return new ApplicationReader(build(), options, timing).read();
  }
}
