// 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.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.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.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 boolean isInterface = false;
    private String access = "public";

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

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

    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 addVirtualMethod(
        String name,
        List<String> argumentTypes,
        String returnType,
        String... lines) {
      makeInit = true;
      return addMethod("public", 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 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);
    }

    private 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 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, 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 (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");
      }
      return builder.toString();
    }

    void setIsInterface() {
      isInterface = true;
    }

    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");
    }
  }

  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);
    return out.toByteArray();
  }

  public List<byte[]> buildClasses() throws Exception {
    List<byte[]> result = new ArrayList<>();
    for (ClassBuilder clazz : classes) {
      result.add(compile(clazz));
    }
    return result;
  }

  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 DexApplication read() throws Exception {
    return read(new InternalOptions());
  }

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