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

import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.Smali;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import org.antlr.runtime.RecognitionException;

public class SmaliBuilder {

  public static class MethodSignature {

    public final String clazz;
    public final String name;
    public final String returnType;
    public final List<String> parameterTypes;

    public MethodSignature(String clazz, String name, String returnType,
        List<String> parameterTypes) {
      this.clazz = clazz;
      this.name = name;
      this.returnType = returnType;
      this.parameterTypes = parameterTypes;
    }

    public static MethodSignature staticInitializer(String clazz) {
      return new MethodSignature(clazz, "<clinit>", "void", ImmutableList.of());
    }

    @Override
    public String toString() {
      return returnType + " " + clazz + "." + name
          + "(" + StringUtils.join(parameterTypes, ",") + ")";
    }
  }

  abstract class Builder {

    String name;
    String superName;
    List<String> implementedInterfaces;
    String sourceFile = null;
    List<String> source = new ArrayList<>();

    Builder(String name, String superName, List<String> implementedInterfaces) {
      this.name = name;
      this.superName = superName;
      this.implementedInterfaces = implementedInterfaces;
    }

    protected void appendSuper(StringBuilder builder) {
      builder.append(".super ");
      builder.append(DescriptorUtils.javaTypeToDescriptor(superName));
      builder.append("\n");
    }

    protected void appendImplementedInterfaces(StringBuilder builder) {
      for (String implementedInterface : implementedInterfaces) {
        builder.append(".implements ");
        builder.append(DescriptorUtils.javaTypeToDescriptor(implementedInterface));
        builder.append("\n");
      }
    }

    protected void writeSource(StringBuilder builder) {
      for (String sourceLine : source) {
        builder.append(sourceLine);
        builder.append("\n");
      }
    }
  }

  public class ClassBuilder extends Builder {

    private boolean isAbstract = false;

    ClassBuilder(String name, String superName, List<String> implementedInterfaces) {
      super(name, superName, implementedInterfaces);
    }

    public ClassBuilder setAbstract() {
      isAbstract = true;
      return this;
    }

    public String toString() {
      StringBuilder builder = new StringBuilder();
      builder.append(".class public ");
      if (isAbstract) {
        builder.append("abstract ");
      }
      builder.append(DescriptorUtils.javaTypeToDescriptor(name));
      builder.append("\n");
      appendSuper(builder);
      appendImplementedInterfaces(builder);
      builder.append("\n");
      if (sourceFile != null) {
        builder.append(".source \"").append(sourceFile).append("\"\n");
      }
      writeSource(builder);
      return builder.toString();
    }
  }

  public class InterfaceBuilder extends Builder {

    InterfaceBuilder(String name, String superName, List<String> implementedInterfaces) {
      super(name, superName, implementedInterfaces);
    }

    public String toString() {
      StringBuilder builder = new StringBuilder();
      builder.append(".class public interface abstract ");
      builder.append(DescriptorUtils.javaTypeToDescriptor(name));
      builder.append("\n");
      appendSuper(builder);
      appendImplementedInterfaces(builder);
      builder.append("\n");
      writeSource(builder);
      return builder.toString();
    }
  }

  private String currentClassName;
  private final Map<String, Builder> classes = new HashMap<>();
  private AndroidApiLevel minApi = AndroidApiLevel.I_MR1;

  public SmaliBuilder() {
    // No default class.
  }

  public SmaliBuilder(String name) {
    addClass(name);
  }

  public SmaliBuilder(String name, String superName) {
    addClass(name, superName);
  }

  public void setMinApi(AndroidApiLevel minApi) {
    this.minApi = minApi;
  }

  private List<String> getSource(String clazz) {
    return classes.get(clazz).source;
  }

  public String getCurrentClassName() {
    return currentClassName;
  }

  public String getCurrentClassDescriptor() {
    return DescriptorUtils.javaTypeToDescriptor(currentClassName);
  }

  public void addClass(String name) {
    addClass(name, "java.lang.Object");
  }

  public void addClass(String name, String superName) {
    addClass(name, superName, ImmutableList.of());
  }

  public ClassBuilder addClass(String name, String superName, List<String> implementedInterfaces) {
    assert !classes.containsKey(name);
    currentClassName = name;
    ClassBuilder classBuilder = new ClassBuilder(name, superName, implementedInterfaces);
    classes.put(name, classBuilder);
    return classBuilder;
  }

  public void addInterface(String name) {
    addInterface(name, "java.lang.Object");
  }

  public void addInterface(String name, String superName) {
    addInterface(name, superName, ImmutableList.of());
  }

  public void addInterface(String name, String superName, List<String> implementedInterfaces) {
    assert !classes.containsKey(name);
    currentClassName = name;
    classes.put(name, new InterfaceBuilder(name, superName, implementedInterfaces));
  }

  public void setSourceFile(String file) {
    classes.get(currentClassName).sourceFile = file;
  }

  public void addDefaultConstructor() {
    String superDescriptor =
        DescriptorUtils.javaTypeToDescriptor(classes.get(currentClassName).superName);
    addMethodRaw(
        "  .method public constructor <init>()V",
        "    .locals 0",
        "    invoke-direct {p0}, " + superDescriptor + "-><init>()V",
        "    return-void",
        "  .end method"
    );
  }

  public void addStaticField(String name, String type, String defaultValue) {
    StringBuilder builder = new StringBuilder();
    builder.append(".field static ");
    builder.append(name);
    builder.append(":");
    builder.append(type);
    if (defaultValue != null) {
      builder.append(" = ");
      if (type.equals("Ljava/lang/String;")) {
        builder.append('"');
        builder.append(defaultValue);
        builder.append('"');
      } else {
        builder.append(defaultValue);
      }
    }
    getSource(currentClassName).add(builder.toString());
  }

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

  public void addInstanceField(String name, String type) {
    StringBuilder builder = new StringBuilder();
    builder.append(".field ");
    builder.append(name);
    builder.append(":");
    builder.append(type);
    getSource(currentClassName).add(builder.toString());
  }

  private MethodSignature addMethod(String flags, String returnType, String name,
      List<String> parameters, int locals, String code) {
    StringBuilder builder = new StringBuilder();
    builder.append(".method ");
    if (flags != null && flags.length() > 0) {
      builder.append(flags);
      builder.append(" ");
    }
    builder.append(name);
    builder.append("(");
    for (String parameter : parameters) {
      builder.append(DescriptorUtils.javaTypeToDescriptor(parameter));
    }
    builder.append(")");
    builder.append(DescriptorUtils.javaTypeToDescriptor(returnType));
    builder.append("\n");
    if (locals >= 0) {
      builder.append(".locals ");
      builder.append(locals);
      builder.append("\n\n");
      assert code != null;
      builder.append(code);
    } else {
      assert code == null;
    }
    builder.append(".end method");
    getSource(currentClassName).add(builder.toString());
    return new MethodSignature(currentClassName, name, returnType, parameters);
  }

  public MethodSignature addStaticMethod(
      String returnType, String name, List<String> parameters, int locals, String... instructions) {
    return addStaticMethod(returnType, name, parameters, locals, buildCode(instructions));
  }

  public MethodSignature addPrivateStaticMethod(
      String returnType, String name, List<String> parameters, int locals, String... instructions) {
    return addMethod(
        "private static", returnType, name, parameters, locals, buildCode(instructions));
  }

  public MethodSignature addStaticMethod(
      String returnType, String name, List<String> parameters, int locals, String code) {
    return addStaticMethod("", returnType, name, parameters, locals, code);
  }

  public MethodSignature addStaticInitializer(int locals, String... instructions) {
    return addStaticInitializer(locals, buildCode(instructions));
  }

  public MethodSignature addStaticInitializer(int locals, String code) {
    return addStaticMethod("constructor", "void", "<clinit>", ImmutableList.of(), locals, code);
  }

  private MethodSignature addStaticMethod(
      String flags,
      String returnType,
      String name,
      List<String> parameters,
      int locals,
      String code) {
    return addMethod("public static " + flags, returnType, name, parameters, locals, code);
  }

  public MethodSignature addAbstractMethod(
      String returnType, String name, List<String> parameters) {
    return addMethod("public abstract", returnType, name, parameters, -1, null);
  }

  public MethodSignature addInitializer(int locals, String... instructions) {
    return addMethod(
        "public constructor",
        "void",
        "<init>",
        ImmutableList.of(),
        locals,
        buildCode(instructions));
  }

  public MethodSignature addInitializer(
      List<String> parameters, int locals, String... instructions) {
    return addMethod(
        "public constructor", "void", "<init>", parameters, locals, buildCode(instructions));
  }

  public MethodSignature addPrivateInstanceMethod(
      String returnType, String name, List<String> parameters, int locals, String... instructions) {
    return addMethod("private", returnType, name, parameters, locals, buildCode(instructions));
  }

  public MethodSignature addInstanceMethod(
      String returnType, String name, int locals, String... instructions) {
    return addInstanceMethod(returnType, name, ImmutableList.of(), locals, buildCode(instructions));
  }

  public MethodSignature addInstanceMethod(
      String returnType, String name, List<String> parameters, int locals, String... instructions) {
    return addInstanceMethod(returnType, name, parameters, locals, buildCode(instructions));
  }

  public MethodSignature addInstanceMethod(
      String returnType, String name, List<String> parameters, int locals, String code) {
    return addMethod("public", returnType, name, parameters, locals, code);
  }

  public MethodSignature addMainMethod(int locals, String... instructions) {
    return addStaticMethod(
        "void", "main", Collections.singletonList("java.lang.String[]"), locals, instructions);
  }

  public void addMethodRaw(String... source) {
    StringBuilder builder = new StringBuilder();
    for (String line : source) {
      builder.append(line);
      builder.append(System.lineSeparator());
    }
    getSource(currentClassName).add(builder.toString());
  }

  public static String buildCode(String... instructions) {
    StringBuilder builder = new StringBuilder();
    for (String instruction : instructions) {
      builder.append(instruction);
      builder.append(System.lineSeparator());
    }
    return builder.toString();
  }

  public List<String> buildSource() {
    List<String> result = new ArrayList<>(classes.size());
    for (String clazz : classes.keySet()) {
      Builder classBuilder = classes.get(clazz);
      result.add(classBuilder.toString());
    }
    return result;
  }

  public byte[] compile() throws IOException, RecognitionException, ExecutionException {
    return Smali.compile(buildSource(), minApi.getLevel());
  }

  public AndroidApp build() throws IOException, RecognitionException, ExecutionException {
    return AndroidApp.builder().addDexProgramData(compile(), Origin.unknown()).build();
  }


  @Override
  public String toString() {
    return String.join("\n\n", buildSource());
  }
}
