// 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.ir.optimize.enums;

import com.android.tools.r8.cf.CfVersion;
import com.android.tools.r8.cf.code.CfArrayStore;
import com.android.tools.r8.cf.code.CfConstNumber;
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.cf.code.CfLoad;
import com.android.tools.r8.cf.code.CfNewArray;
import com.android.tools.r8.cf.code.CfReturn;
import com.android.tools.r8.cf.code.CfReturnVoid;
import com.android.tools.r8.cf.code.CfStackInstruction;
import com.android.tools.r8.cf.code.CfStackInstruction.Opcode;
import com.android.tools.r8.cf.code.CfStaticFieldRead;
import com.android.tools.r8.cf.code.CfStaticFieldWrite;
import com.android.tools.r8.cf.code.CfStore;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.ClassAccessFlags;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexProgramClass;
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.FieldAccessFlags;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.MemberType;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.FieldAccessInfoCollectionModifier;
import com.android.tools.r8.synthesis.SyntheticMethodBuilder.SyntheticCodeGenerator;
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.utils.ConsumerUtils;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.objectweb.asm.Opcodes;

public class SharedEnumUnboxingUtilityClass extends EnumUnboxingUtilityClass {

  private final DexProgramClass sharedUtilityClass;
  private final ProgramMethod valuesMethod;

  public SharedEnumUnboxingUtilityClass(
      DexProgramClass sharedUtilityClass,
      DexProgramClass synthesizingContext,
      ProgramMethod valuesMethod) {
    super(synthesizingContext);
    this.sharedUtilityClass = sharedUtilityClass;
    this.valuesMethod = valuesMethod;
  }

  public static Builder builder(
      AppView<AppInfoWithLiveness> appView,
      EnumDataMap enumDataMap,
      Set<DexProgramClass> enumsToUnbox,
      FieldAccessInfoCollectionModifier.Builder fieldAccessInfoCollectionModifierBuilder) {
    return new Builder(
        appView, enumDataMap, enumsToUnbox, fieldAccessInfoCollectionModifierBuilder);
  }

  @Override
  public void ensureMethods(AppView<AppInfoWithLiveness> appView) {
    ensureCheckNotZeroMethod(appView);
    ensureCheckNotZeroWithMessageMethod(appView);
    ensureCompareToMethod(appView);
    ensureEqualsMethod(appView);
    ensureOrdinalMethod(appView);
  }

  public ProgramMethod ensureCheckNotZeroMethod(AppView<AppInfoWithLiveness> appView) {
    DexItemFactory dexItemFactory = appView.dexItemFactory();
    return internalEnsureMethod(
        appView,
        dexItemFactory.createString("checkNotZero"),
        dexItemFactory.createProto(dexItemFactory.voidType, dexItemFactory.intType),
        method -> EnumUnboxingCfMethods.EnumUnboxingMethods_zeroCheck(appView.options(), method));
  }

  public ProgramMethod ensureCheckNotZeroWithMessageMethod(AppView<AppInfoWithLiveness> appView) {
    DexItemFactory dexItemFactory = appView.dexItemFactory();
    return internalEnsureMethod(
        appView,
        dexItemFactory.createString("checkNotZero"),
        dexItemFactory.createProto(
            dexItemFactory.voidType, dexItemFactory.intType, dexItemFactory.stringType),
        method ->
            EnumUnboxingCfMethods.EnumUnboxingMethods_zeroCheckMessage(appView.options(), method));
  }

  public ProgramMethod ensureCompareToMethod(AppView<AppInfoWithLiveness> appView) {
    DexItemFactory dexItemFactory = appView.dexItemFactory();
    return internalEnsureMethod(
        appView,
        dexItemFactory.enumMembers.compareTo.getName(),
        dexItemFactory.createProto(
            dexItemFactory.intType, dexItemFactory.intType, dexItemFactory.intType),
        method -> EnumUnboxingCfMethods.EnumUnboxingMethods_compareTo(appView.options(), method));
  }

  public ProgramMethod ensureEqualsMethod(AppView<AppInfoWithLiveness> appView) {
    DexItemFactory dexItemFactory = appView.dexItemFactory();
    return internalEnsureMethod(
        appView,
        dexItemFactory.enumMembers.equals.getName(),
        dexItemFactory.createProto(
            dexItemFactory.booleanType, dexItemFactory.intType, dexItemFactory.intType),
        method -> EnumUnboxingCfMethods.EnumUnboxingMethods_equals(appView.options(), method));
  }

  public ProgramMethod ensureOrdinalMethod(AppView<AppInfoWithLiveness> appView) {
    DexItemFactory dexItemFactory = appView.dexItemFactory();
    return internalEnsureMethod(
        appView,
        dexItemFactory.enumMembers.ordinalMethod.getName(),
        dexItemFactory.createProto(dexItemFactory.intType, dexItemFactory.intType),
        method -> EnumUnboxingCfMethods.EnumUnboxingMethods_ordinal(appView.options(), method));
  }

  private ProgramMethod internalEnsureMethod(
      AppView<AppInfoWithLiveness> appView,
      DexString methodName,
      DexProto methodProto,
      SyntheticCodeGenerator codeGenerator) {
    // TODO(b/191957637): Consider creating free flowing static methods instead. The synthetic
    //  infrastructure needs to be augmented with a new method ensureFixedMethod() or
    //  ensureFixedFreeFlowingMethod() for this, if we want to create only one utility method (and
    //  not one per use context).
    return appView
        .getSyntheticItems()
        .ensureFixedClassMethod(
            methodName,
            methodProto,
            SyntheticKind.ENUM_UNBOXING_SHARED_UTILITY_CLASS,
            getSynthesizingContext(),
            appView,
            ConsumerUtils.emptyConsumer(),
            methodBuilder ->
                methodBuilder
                    .setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
                    .setApiLevelForDefinition(appView.computedMinApiLevel())
                    .setApiLevelForCode(appView.computedMinApiLevel())
                    .setCode(codeGenerator)
                    .setClassFileVersion(CfVersion.V1_6));
  }

  @Override
  public DexProgramClass getDefinition() {
    return sharedUtilityClass;
  }

  public ProgramMethod getValuesMethod() {
    return valuesMethod;
  }

  public DexType getType() {
    return sharedUtilityClass.getType();
  }

  public static class Builder {

    private final AppView<AppInfoWithLiveness> appView;
    private final DexItemFactory dexItemFactory;
    private final EnumDataMap enumDataMap;
    private final FieldAccessInfoCollectionModifier.Builder
        fieldAccessInfoCollectionModifierBuilder;
    private final DexProgramClass synthesizingContext;

    private DexEncodedMethod valuesMethod;

    private Builder(
        AppView<AppInfoWithLiveness> appView,
        EnumDataMap enumDataMap,
        Set<DexProgramClass> enumsToUnbox,
        FieldAccessInfoCollectionModifier.Builder fieldAccessInfoCollectionModifierBuilder) {
      DexProgramClass synthesizingContext = findDeterministicContextType(enumsToUnbox);
      this.appView = appView;
      this.dexItemFactory = appView.dexItemFactory();
      this.enumDataMap = enumDataMap;
      this.fieldAccessInfoCollectionModifierBuilder = fieldAccessInfoCollectionModifierBuilder;
      this.synthesizingContext = synthesizingContext;
    }

    SharedEnumUnboxingUtilityClass build() {
      DexProgramClass clazz = createClass();
      SharedEnumUnboxingUtilityClass sharedUtilityClass =
          new SharedEnumUnboxingUtilityClass(
              clazz, synthesizingContext, new ProgramMethod(clazz, valuesMethod));
      return sharedUtilityClass;
    }

    private DexProgramClass createClass() {
      DexProgramClass clazz =
          appView
              .getSyntheticItems()
              .createFixedClass(
                  SyntheticKind.ENUM_UNBOXING_SHARED_UTILITY_CLASS,
                  synthesizingContext,
                  appView,
                  classBuilder -> {
                    DexType sharedUtilityClassType = classBuilder.getType();
                    DexEncodedField valuesField = createValuesField(sharedUtilityClassType);
                    classBuilder
                        .setDirectMethods(
                            ImmutableList.of(
                                createClassInitializer(sharedUtilityClassType, valuesField),
                                createValuesMethod(sharedUtilityClassType, valuesField)))
                        .setStaticFields(ImmutableList.of(valuesField))
                        .setUseSortedMethodBacking(true);
                  });
      assert clazz.getAccessFlags().equals(ClassAccessFlags.createPublicFinalSynthetic());
      return clazz;
    }

    // Fields.

    private DexEncodedField createValuesField(DexType sharedUtilityClassType) {
      DexEncodedField valuesField =
          DexEncodedField.syntheticBuilder()
              .setField(
                  dexItemFactory.createField(
                      sharedUtilityClassType, dexItemFactory.intArrayType, "$VALUES"))
              .setAccessFlags(FieldAccessFlags.createPublicStaticFinalSynthetic())
              .setApiLevel(appView.computedMinApiLevel())
              .build();
      fieldAccessInfoCollectionModifierBuilder
          .recordFieldReadInUnknownContext(valuesField.getReference())
          .recordFieldWriteInUnknownContext(valuesField.getReference());
      return valuesField;
    }

    // Methods.

    private DexEncodedMethod createClassInitializer(
        DexType sharedUtilityClassType, DexEncodedField valuesField) {
      return DexEncodedMethod.syntheticBuilder()
          .setMethod(dexItemFactory.createClassInitializer(sharedUtilityClassType))
          .setAccessFlags(MethodAccessFlags.createForClassInitializer())
          .setCode(createClassInitializerCode(sharedUtilityClassType, valuesField))
          .setClassFileVersion(CfVersion.V1_6)
          .setApiLevelForDefinition(appView.computedMinApiLevel())
          .setApiLevelForCode(appView.computedMinApiLevel())
          .build();
    }

    private CfCode createClassInitializerCode(
        DexType sharedUtilityClassType, DexEncodedField valuesField) {
      int maxValuesArraySize = enumDataMap.getMaxValuesSize();
      int numberOfInstructions = 4 + maxValuesArraySize * 4;
      List<CfInstruction> instructions = new ArrayList<>(numberOfInstructions);
      instructions.add(new CfConstNumber(maxValuesArraySize, ValueType.INT));
      instructions.add(new CfNewArray(dexItemFactory.intArrayType));
      for (int i = 0; i < maxValuesArraySize; i++) {
        instructions.add(new CfStackInstruction(Opcode.Dup));
        instructions.add(new CfConstNumber(i, ValueType.INT));
        // i + 1 because 0 represents the null value.
        instructions.add(new CfConstNumber(i + 1, ValueType.INT));
        instructions.add(new CfArrayStore(MemberType.INT));
      }
      instructions.add(new CfStaticFieldWrite(valuesField.getReference()));
      instructions.add(new CfReturnVoid());

      int maxStack = 4;
      int maxLocals = 0;
      return new CfCode(sharedUtilityClassType, maxStack, maxLocals, instructions);
    }

    private DexEncodedMethod createValuesMethod(
        DexType sharedUtilityClassType, DexEncodedField valuesField) {
      DexEncodedMethod valuesMethod =
          DexEncodedMethod.syntheticBuilder()
              .setMethod(
                  dexItemFactory.createMethod(
                      sharedUtilityClassType,
                      dexItemFactory.createProto(
                          dexItemFactory.intArrayType, dexItemFactory.intType),
                      "values"))
              .setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
              .setCode(createValuesMethodCode(sharedUtilityClassType, valuesField))
              .setClassFileVersion(CfVersion.V1_6)
              .setApiLevelForDefinition(appView.computedMinApiLevel())
              .setApiLevelForCode(appView.computedMinApiLevel())
              .build();
      this.valuesMethod = valuesMethod;
      return valuesMethod;
    }

    private CfCode createValuesMethodCode(
        DexType sharedUtilityClassType, DexEncodedField valuesField) {
      int maxStack = 5;
      int maxLocals = 2;
      int argumentLocalSlot = 0;
      int resultLocalSlot = 1;
      return new CfCode(
          sharedUtilityClassType,
          maxStack,
          maxLocals,
          ImmutableList.of(
              // int[] result = new int[size];
              new CfLoad(ValueType.INT, argumentLocalSlot),
              new CfNewArray(dexItemFactory.intArrayType),
              new CfStore(ValueType.OBJECT, resultLocalSlot),
              // System.arraycopy(SharedUtilityClass.$VALUES, 0, result, 0, size);
              new CfStaticFieldRead(valuesField.getReference()),
              new CfConstNumber(0, ValueType.INT),
              new CfLoad(ValueType.OBJECT, resultLocalSlot),
              new CfConstNumber(0, ValueType.INT),
              new CfLoad(ValueType.INT, argumentLocalSlot),
              new CfInvoke(
                  Opcodes.INVOKESTATIC, dexItemFactory.javaLangSystemMethods.arraycopy, false),
              // return result
              new CfLoad(ValueType.OBJECT, resultLocalSlot),
              new CfReturn(ValueType.OBJECT)));
    }

    private static DexProgramClass findDeterministicContextType(Set<DexProgramClass> contexts) {
      DexProgramClass deterministicContext = null;
      for (DexProgramClass context : contexts) {
        if (deterministicContext == null) {
          deterministicContext = context;
        } else if (context.type.compareTo(deterministicContext.type) < 0) {
          deterministicContext = context;
        }
      }
      return deterministicContext;
    }
  }
}
