// Copyright (c) 2021, 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.ir.desugar.stringconcat;

import com.android.tools.r8.cf.code.CfConstString;
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.cf.code.CfInvokeDynamic;
import com.android.tools.r8.cf.code.CfLoad;
import com.android.tools.r8.cf.code.CfNew;
import com.android.tools.r8.cf.code.CfStackInstruction;
import com.android.tools.r8.cf.code.CfStackInstruction.Opcode;
import com.android.tools.r8.cf.code.CfStore;
import com.android.tools.r8.contexts.CompilationContext.MethodProcessingContext;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexItemFactory.StringBuildingMethods;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexTypeList;
import com.android.tools.r8.graph.DexValue;
import com.android.tools.r8.graph.DexValue.DexValueString;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.desugar.CfInstructionDesugaring;
import com.android.tools.r8.ir.desugar.CfInstructionDesugaringCollection;
import com.android.tools.r8.ir.desugar.CfInstructionDesugaringEventConsumer;
import com.android.tools.r8.ir.desugar.FreshLocalProvider;
import com.android.tools.r8.ir.desugar.LocalStackAllocator;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.IteratorUtils;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Deque;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.objectweb.asm.Opcodes;

/** String concatenation desugaring rewriter. */
public class StringConcatInstructionDesugaring implements CfInstructionDesugaring {

  private final DexItemFactory factory;
  private final StringBuildingMethods stringBuilderMethods;

  private final Map<DexType, DexMethod> paramTypeToAppendMethod = new IdentityHashMap<>();

  public StringConcatInstructionDesugaring(AppView<?> appView) {
    this.factory = appView.dexItemFactory();
    this.stringBuilderMethods = factory.stringBuilderMethods;

    // Mapping of type parameters to methods of StringBuilder.
    paramTypeToAppendMethod.put(factory.booleanType, stringBuilderMethods.appendBoolean);
    paramTypeToAppendMethod.put(factory.charType, stringBuilderMethods.appendChar);
    paramTypeToAppendMethod.put(factory.byteType, stringBuilderMethods.appendInt);
    paramTypeToAppendMethod.put(factory.shortType, stringBuilderMethods.appendInt);
    paramTypeToAppendMethod.put(factory.intType, stringBuilderMethods.appendInt);
    paramTypeToAppendMethod.put(factory.longType, stringBuilderMethods.appendLong);
    paramTypeToAppendMethod.put(factory.floatType, stringBuilderMethods.appendFloat);
    paramTypeToAppendMethod.put(factory.doubleType, stringBuilderMethods.appendDouble);
    paramTypeToAppendMethod.put(factory.stringType, stringBuilderMethods.appendString);
  }

  @Override
  public Collection<CfInstruction> desugarInstruction(
      CfInstruction instruction,
      FreshLocalProvider freshLocalProvider,
      LocalStackAllocator localStackAllocator,
      CfInstructionDesugaringEventConsumer eventConsumer,
      ProgramMethod context,
      MethodProcessingContext methodProcessingContext,
      CfInstructionDesugaringCollection desugaringCollection,
      DexItemFactory dexItemFactory) {
    if (instruction.isInvokeDynamic()) {
      // We are interested in bootstrap methods StringConcatFactory::makeConcat
      // and StringConcatFactory::makeConcatWthConstants, both are static.
      CfInvokeDynamic invoke = instruction.asInvokeDynamic();
      DexCallSite callSite = invoke.getCallSite();
      if (callSite.bootstrapMethod.type.isInvokeStatic()) {
        DexMethod bootstrapMethod = callSite.bootstrapMethod.asMethod();
        if (bootstrapMethod == factory.stringConcatFactoryMembers.makeConcat) {
          return desugarMakeConcat(invoke, freshLocalProvider, localStackAllocator);
        }
        if (bootstrapMethod == factory.stringConcatFactoryMembers.makeConcatWithConstants) {
          return desugarMakeConcatWithConstants(
              invoke, freshLocalProvider, localStackAllocator, context);
        }
      }
    }
    return null;
  }

  private Collection<CfInstruction> desugarMakeConcat(
      CfInvokeDynamic invoke,
      FreshLocalProvider freshLocalProvider,
      LocalStackAllocator localStackAllocator) {
    DexProto proto = invoke.getCallSite().methodProto;
    DexType[] parameters = proto.parameters.values;

    // Collect chunks.
    ConcatBuilder builder = new ConcatBuilder();
    for (DexType parameter : parameters) {
      ValueType valueType = ValueType.fromDexType(parameter);
      builder.addChunk(
          new ArgumentChunk(
              paramTypeToAppendMethod.getOrDefault(parameter, stringBuilderMethods.appendObject),
              freshLocalProvider.getFreshLocal(valueType.requiredRegisters())));
    }

    // Desugar the instruction.
    return builder.desugar(localStackAllocator);
  }

  private Collection<CfInstruction> desugarMakeConcatWithConstants(
      CfInvokeDynamic invoke,
      FreshLocalProvider freshLocalProvider,
      LocalStackAllocator localStackAllocator,
      ProgramMethod context) {
    DexCallSite callSite = invoke.getCallSite();
    DexProto proto = callSite.methodProto;
    DexTypeList parameters = proto.getParameters();
    List<DexValue> bootstrapArgs = callSite.bootstrapArgs;

    // Get `recipe` string.
    if (bootstrapArgs.isEmpty()) {
      throw error(context, "bootstrap method misses `recipe` argument");
    }

    // Extract recipe.
    DexValueString recipeValue = bootstrapArgs.get(0).asDexValueString();
    if (recipeValue == null) {
      throw error(context, "bootstrap method argument `recipe` must be a string");
    }
    String recipe = recipeValue.getValue().toString();

    // Constant arguments to `recipe`.
    List<DexValue> constantArguments = new ArrayList<>();
    for (int i = 1; i < bootstrapArgs.size(); i++) {
      constantArguments.add(bootstrapArgs.get(i));
    }

    // Collect chunks and patch the instruction.
    ConcatBuilder builder = new ConcatBuilder();
    StringBuilder acc = new StringBuilder();
    int length = recipe.length();
    Iterator<DexValue> constantArgumentsIterator = constantArguments.iterator();
    Iterator<DexType> parameterIterator = parameters.iterator();
    for (int i = 0; i < length; i++) {
      char c = recipe.charAt(i);
      if (c == '\u0001') {
        // Reference to an argument, so we need to flush the accumulated string.
        if (acc.length() > 0) {
          DexString stringConstant = factory.createString(acc.toString());
          builder.addChunk(
              new ConstantChunk(paramTypeToAppendMethod.get(factory.stringType), stringConstant));
          acc.setLength(0);
        }
        if (!parameterIterator.hasNext()) {
          throw error(context, "too many argument references in `recipe`");
        }
        DexType parameter = parameterIterator.next();
        ValueType valueType = ValueType.fromDexType(parameter);
        builder.addChunk(
            new ArgumentChunk(
                paramTypeToAppendMethod.getOrDefault(parameter, stringBuilderMethods.appendObject),
                freshLocalProvider.getFreshLocal(valueType.requiredRegisters())));
      } else if (c == '\u0002') {
        // Reference to a constant. Since it's a constant we just convert it to string and append to
        // `acc`, this way we will avoid calling toString() on every call.
        if (!constantArgumentsIterator.hasNext()) {
          throw error(context, "too many constant references in `recipe`");
        }
        acc.append(convertToString(constantArgumentsIterator.next(), context));
      } else {
        acc.append(c);
      }
    }

    if (parameterIterator.hasNext()) {
      throw error(
          context,
          "too few argument references in `recipe`, "
              + "expected "
              + parameters.size()
              + ", referenced: "
              + (parameters.size() - IteratorUtils.countRemaining(parameterIterator)));
    }

    if (constantArgumentsIterator.hasNext()) {
      throw error(
          context,
          "too few constant references in `recipe`, "
              + "expected "
              + constantArguments.size()
              + ", referenced: "
              + (constantArguments.size()
                  - IteratorUtils.countRemaining(constantArgumentsIterator)));
    }

    // Final part.
    if (acc.length() > 0) {
      DexString stringConstant = factory.createString(acc.toString());
      builder.addChunk(
          new ConstantChunk(paramTypeToAppendMethod.get(factory.stringType), stringConstant));
    }

    // Desugar the instruction.
    return builder.desugar(localStackAllocator);
  }

  @Override
  public boolean needsDesugaring(CfInstruction instruction, ProgramMethod context) {
    return isStringConcatInvoke(instruction, factory);
  }

  public static boolean isStringConcatInvoke(CfInstruction instruction, DexItemFactory factory) {
    CfInvokeDynamic invoke = instruction.asInvokeDynamic();
    if (invoke == null) {
      return false;
    }
    // We are interested in bootstrap methods StringConcatFactory::makeConcat
    // and StringConcatFactory::makeConcatWithConstants, both are static.
    DexCallSite callSite = invoke.getCallSite();
    if (callSite.bootstrapMethod.type.isInvokeStatic()) {
      DexMethod bootstrapMethod = callSite.bootstrapMethod.asMethod();
      return bootstrapMethod == factory.stringConcatFactoryMembers.makeConcat
          || bootstrapMethod == factory.stringConcatFactoryMembers.makeConcatWithConstants;
    }
    return false;
  }

  private static String convertToString(DexValue value, ProgramMethod context) {
    if (value.isDexValueString()) {
      return value.asDexValueString().getValue().toString();
    }
    throw error(
        context,
        "const arg referenced from `recipe` is not supported: " + value.getClass().getName());
  }

  private final class ConcatBuilder {

    private final List<Chunk> chunks = new ArrayList<>();

    private ArgumentChunk biggestArgumentChunk = null;
    private ConstantChunk firstConstantChunk = null;
    private int argumentChunksStackSize = 0;

    ConcatBuilder() {}

    void addChunk(ArgumentChunk chunk) {
      chunks.add(chunk);
      argumentChunksStackSize += chunk.getValueType().requiredRegisters();
      if (biggestArgumentChunk == null
          || chunk.getValueType().requiredRegisters()
              > biggestArgumentChunk.getValueType().requiredRegisters()) {
        biggestArgumentChunk = chunk;
      }
    }

    void addChunk(ConstantChunk chunk) {
      chunks.add(chunk);
      if (firstConstantChunk == null) {
        firstConstantChunk = chunk;
      }
    }

    /**
     * Patch current `invoke-custom` instruction with:
     *
     * <pre>
     *   prologue:
     *      |   new-instance v0, StringBuilder
     *      |   invoke-direct {v0}, void StringBuilder.<init>()
     *
     *   populate each chunk:
     *      |   (optional) load the constant, e.g.: const-string v1, ""
     *      |   invoke-virtual {v0, v1}, StringBuilder StringBuilder.append([type])
     *
     *   epilogue:
     *      |   invoke-virtual {v0}, String StringBuilder.toString()
     *
     * </pre>
     */
    final Collection<CfInstruction> desugar(LocalStackAllocator localStackAllocator) {
      Deque<CfInstruction> replacement = new ArrayDeque<>();
      for (Chunk chunk : chunks) {
        if (chunk.isArgumentChunk()) {
          ArgumentChunk argumentChunk = chunk.asArgumentChunk();
          replacement.addFirst(
              new CfStore(argumentChunk.getValueType(), argumentChunk.getVariableIndex()));
        }
      }
      replacement.add(new CfNew(factory.stringBuilderType));
      replacement.add(new CfStackInstruction(Opcode.Dup));
      replacement.add(
          new CfInvoke(Opcodes.INVOKESPECIAL, stringBuilderMethods.defaultConstructor, false));
      for (Chunk chunk : chunks) {
        if (chunk.isArgumentChunk()) {
          ArgumentChunk argumentChunk = chunk.asArgumentChunk();
          replacement.add(
              new CfLoad(argumentChunk.getValueType(), argumentChunk.getVariableIndex()));
        } else {
          assert chunk.isConstantChunk();
          replacement.add(new CfConstString(chunk.asConstantChunk().getStringConstant()));
        }
        replacement.add(new CfInvoke(Opcodes.INVOKEVIRTUAL, chunk.method, false));
      }
      replacement.add(new CfInvoke(Opcodes.INVOKEVIRTUAL, stringBuilderMethods.toString, false));

      // Coming into the original invoke-dynamic instruction, we have N arguments on the stack. We
      // then pop the N arguments from the stack, allocate a new-instance on the stack, and dup it,
      // to initialize the instance. We then one-by-one load the arguments and call append(). We
      // therefore need a local stack of size 3 if there is a wide argument, and otherwise a local
      // stack of size 2.
      int maxLocalStackSizeAfterStores =
          2
              + BooleanUtils.intValue(
                  biggestArgumentChunk != null
                      && biggestArgumentChunk.getValueType().requiredRegisters() == 2);
      if (maxLocalStackSizeAfterStores > argumentChunksStackSize) {
        localStackAllocator.allocateLocalStack(
            maxLocalStackSizeAfterStores - argumentChunksStackSize);
      }
      return replacement;
    }
  }

  private abstract static class Chunk {

    private final DexMethod method;

    Chunk(DexMethod method) {
      this.method = method;
    }

    public DexMethod getMethod() {
      return method;
    }

    public ValueType getValueType() {
      assert method.getProto().getArity() == 1;
      return ValueType.fromDexType(method.getParameter(0));
    }

    public boolean isArgumentChunk() {
      return false;
    }

    public ArgumentChunk asArgumentChunk() {
      return null;
    }

    public boolean isConstantChunk() {
      return false;
    }

    public ConstantChunk asConstantChunk() {
      return null;
    }
  }

  private static final class ArgumentChunk extends Chunk {

    private final int variableIndex;

    ArgumentChunk(DexMethod method, int variableIndex) {
      super(method);
      this.variableIndex = variableIndex;
    }

    public int getVariableIndex() {
      return variableIndex;
    }

    @Override
    public boolean isArgumentChunk() {
      return true;
    }

    @Override
    public ArgumentChunk asArgumentChunk() {
      return this;
    }
  }

  private static final class ConstantChunk extends Chunk {

    private final DexString stringConstant;

    ConstantChunk(DexMethod method, DexString stringConstant) {
      super(method);
      this.stringConstant = stringConstant;
    }

    public DexString getStringConstant() {
      return stringConstant;
    }

    @Override
    public boolean isConstantChunk() {
      return true;
    }

    @Override
    public ConstantChunk asConstantChunk() {
      return this;
    }
  }

  private static CompilationError error(ProgramMethod context, String message) {
    return new CompilationError(
        "String concatenation desugaring error (method: "
            + context.toSourceString()
            + "): "
            + message);
  }
}
