// Copyright (c) 2020, 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.horizontalclassmerging;

import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.ConstNumber;
import com.android.tools.r8.ir.code.InvokeType;
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.conversion.IRBuilder;
import com.android.tools.r8.ir.synthetic.SyntheticSourceCode;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.IntBox;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap.Entry;
import it.unimi.dsi.fastutil.ints.Int2ReferenceSortedMap;
import java.util.ArrayList;
import java.util.List;

/**
 * Generate code of the form: <code>
 *   MyClass(int constructorId, [args]) {
 *     switch (constructorId) {
 *       case 1:
 *         this.Constructor$B([args]);
 *         return;
 *       ...
 *       default:
 *         this.Constructor$A([args]);
 *         return;
 *     }
 *   }
 * </code>
 */
public class ConstructorEntryPoint extends SyntheticSourceCode {

  private final DexField classIdField;
  private final int numberOfUnusedArguments;
  private final ProgramMethod method;
  private final Int2ReferenceSortedMap<DexMethod> typeConstructors;

  public ConstructorEntryPoint(
      Int2ReferenceSortedMap<DexMethod> typeConstructors,
      ProgramMethod method,
      DexField classIdField,
      int numberOfUnusedArguments,
      Position position) {
    super(method, position);
    this.classIdField = classIdField;
    this.numberOfUnusedArguments = numberOfUnusedArguments;
    this.method = method;
    this.typeConstructors = typeConstructors;
  }

  private boolean hasClassIdField() {
    return classIdField != null;
  }

  void addConstructorInvoke(DexMethod typeConstructor) {
    add(
        builder -> {
          int originalNumberOfNonReceiverArguments =
              builder.hasArgumentValues()
                  ? (builder.getArgumentValues().size()
                      - BooleanUtils.intValue(typeConstructors.size() > 1)
                      - numberOfUnusedArguments)
                  : 0;
          int newNumberOfNonReceiverArguments = typeConstructor.getArity();
          List<Value> arguments = new ArrayList<>(newNumberOfNonReceiverArguments + 1);
          arguments.add(builder.getReceiverValue());
          if (originalNumberOfNonReceiverArguments >= newNumberOfNonReceiverArguments) {
            for (int i = 0; i < newNumberOfNonReceiverArguments; i++) {
              arguments.add(builder.getArgumentValues().get(i));
            }
          } else {
            // Exclude the last argument if it is the synthetic class id parameter, since the
            // original constructor we are calling does not have it.
            for (int i = 0; i < originalNumberOfNonReceiverArguments; i++) {
              arguments.add(builder.getArgumentValues().get(i));
            }
            int extraRegister = nextRegister(ValueType.INT);
            ConstNumber constNumber = builder.addIntConst(extraRegister, 0);
            while (arguments.size() <= newNumberOfNonReceiverArguments) {
              assert ValueType.fromDexType(
                      typeConstructor.getArgumentTypeForNonStaticMethod(arguments.size()))
                  == ValueType.INT;
              arguments.add(constNumber.outValue());
            }
          }
          assert arguments.size() == typeConstructor.getNumberOfArgumentsForNonStaticMethod();
          builder.addInvoke(
              InvokeType.DIRECT, typeConstructor, typeConstructor.getProto(), arguments, false);
        });
  }

  /** Assign the given register to the class id field. */
  void addRegisterClassIdAssignment(int classIdRegister) {
    assert hasClassIdField();
    add(builder -> builder.addInstancePut(classIdRegister, getReceiverRegister(), classIdField));
  }

  protected void prepareMultiConstructorInstructions() {
    int typeConstructorCount = typeConstructors.size();
    // The class id register is always the first synthetic argument.
    int classIdRegister = getParamRegister(method.getArity() - 1 - numberOfUnusedArguments);
    if (hasClassIdField()) {
      addRegisterClassIdAssignment(classIdRegister);
    }

    int[] keys = new int[typeConstructorCount - 1];
    int[] offsets = new int[typeConstructorCount - 1];
    IntBox fallthrough = new IntBox();
    int switchIndex = lastInstructionIndex();
    add(
        builder -> builder.addSwitch(classIdRegister, keys, fallthrough.get(), offsets),
        builder -> endsSwitch(builder, switchIndex, fallthrough.get(), offsets));

    int index = 0;
    for (Entry<DexMethod> entry : typeConstructors.int2ReferenceEntrySet()) {
      int classId = entry.getIntKey();
      DexMethod typeConstructor = entry.getValue();

      if (index == 0) {
        // The first constructor is the fallthrough case.
        fallthrough.set(nextInstructionIndex());
      } else {
        // All subsequent constructors are matched on a specific case.
        keys[index - 1] = classId;
        offsets[index - 1] = nextInstructionIndex();
      }

      addConstructorInvoke(typeConstructor);
      add(IRBuilder::addReturn, endsBlock);

      index++;
    }
  }

  protected void prepareSingleConstructorInstructions() {
    Entry<DexMethod> entry = typeConstructors.int2ReferenceEntrySet().first();
    if (hasClassIdField()) {
      int classIdRegister = nextRegister(ValueType.INT);
      int classIdValue = entry.getIntKey();
      add(builder -> builder.addIntConst(classIdRegister, classIdValue));
      addRegisterClassIdAssignment(classIdRegister);
    }
    addConstructorInvoke(entry.getValue());
    add(IRBuilder::addReturn, endsBlock);
  }

  @Override
  protected void prepareInstructions() {
    if (typeConstructors.size() > 1) {
      prepareMultiConstructorInstructions();
    } else {
      prepareSingleConstructorInstructions();
    }
  }
}
