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

import static com.android.tools.r8.ir.optimize.ReflectionOptimizer.computeClassName;
import static com.android.tools.r8.utils.DescriptorUtils.descriptorToJavaType;

import com.android.tools.r8.cf.code.CfConstString;
import com.android.tools.r8.cf.code.CfDexItemBasedConstString;
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.code.ConstString;
import com.android.tools.r8.code.DexItemBasedConstString;
import com.android.tools.r8.code.Instruction;
import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexValue;
import com.android.tools.r8.graph.DexValue.DexItemBasedValueString;
import com.android.tools.r8.graph.DexValue.DexValueString;
import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import com.android.tools.r8.shaking.ProguardClassFilter;
import java.util.List;
import java.util.Map;

/**
 * Replaces all instances of DexItemBasedConstString by ConstString, and all instances of
 * DexItemBasedValueString by DexValueString.
 */
class IdentifierMinifier {

  private final AppInfoWithLiveness appInfo;
  private final ProguardClassFilter adaptClassStrings;
  private final NamingLens lens;

  IdentifierMinifier(
      AppInfoWithLiveness appInfo, ProguardClassFilter adaptClassStrings, NamingLens lens) {
    this.appInfo = appInfo;
    this.adaptClassStrings = adaptClassStrings;
    this.lens = lens;
  }

  void run() {
    if (!adaptClassStrings.isEmpty()) {
      adaptClassStrings();
    }
    replaceDexItemBasedConstString();
  }

  private void adaptClassStrings() {
    for (DexProgramClass clazz : appInfo.classes()) {
      if (adaptClassStrings.matches(clazz.type)) {
        for (DexEncodedField field : clazz.staticFields()) {
          adaptClassStringsInStaticField(field);
        }
        clazz.forEachMethod(this::adaptClassStringsInMethod);
      }
    }
  }

  private void adaptClassStringsInStaticField(DexEncodedField encodedField) {
    assert encodedField.accessFlags.isStatic();
    DexValue staticValue = encodedField.getStaticValue();
    if (staticValue instanceof DexValueString) {
      DexString original = ((DexValueString) staticValue).getValue();
      encodedField.setStaticValue(new DexValueString(getRenamedStringLiteral(original)));
    }
  }

  private void adaptClassStringsInMethod(DexEncodedMethod encodedMethod) {
    // Abstract methods do not have code_item.
    if (encodedMethod.shouldNotHaveCode()) {
      return;
    }
    Code code = encodedMethod.getCode();
    if (code == null) {
      return;
    }
    if (code.isDexCode()) {
      for (Instruction instruction : code.asDexCode().instructions) {
        if (instruction.isConstString()) {
          ConstString cnst = instruction.asConstString();
          cnst.BBBB = getRenamedStringLiteral(cnst.getString());
        }
      }
    } else {
      assert code.isCfCode();
      for (CfInstruction instruction : code.asCfCode().getInstructions()) {
        if (instruction.isConstString()) {
          CfConstString cnst = instruction.asConstString();
          cnst.setString(getRenamedStringLiteral(cnst.getString()));
        }
      }
    }
  }

  private DexString getRenamedStringLiteral(DexString originalLiteral) {
    String originalString = originalLiteral.toString();
    Map<String, DexType> renamedYetMatchedTypes =
        lens.getRenamedItems(
            DexType.class,
            type -> type.toSourceString().equals(originalString),
            DexType::toSourceString);
    DexType type = renamedYetMatchedTypes.get(originalString);
    if (type != null) {
      DexString renamed = lens.lookupDescriptor(type);
      // Create a new DexString only when the corresponding string literal will be replaced.
      if (renamed != originalLiteral) {
        return appInfo.dexItemFactory.createString(descriptorToJavaType(renamed.toString()));
      }
    }
    return originalLiteral;
  }

  private void replaceDexItemBasedConstString() {
    for (DexProgramClass clazz : appInfo.classes()) {
      // Some const strings could be moved to field's static value (from <clinit>).
      for (DexEncodedField field : clazz.staticFields()) {
        replaceDexItemBasedConstStringInStaticField(field);
      }
      clazz.forEachMethod(this::replaceDexItemBasedConstStringInMethod);
    }
  }

  private void replaceDexItemBasedConstStringInStaticField(DexEncodedField encodedField) {
    assert encodedField.accessFlags.isStatic();
    DexValue staticValue = encodedField.getStaticValue();
    if (staticValue instanceof DexItemBasedValueString) {
      DexItemBasedValueString dexItemBasedValueString = (DexItemBasedValueString) staticValue;
      DexReference original = dexItemBasedValueString.getValue();
      DexString replacement =
          dexItemBasedValueString.getClassNameComputationInfo().needsToComputeClassName()
              ? appInfo.dexItemFactory.createString(
                  computeClassName(
                      lens.lookupDescriptor(original.asDexType()),
                      appInfo.definitionFor(original.asDexType()),
                      dexItemBasedValueString.getClassNameComputationInfo()))
              : lens.lookupName(original, appInfo.dexItemFactory);
      encodedField.setStaticValue(new DexValueString(replacement));
    }
  }

  private void replaceDexItemBasedConstStringInMethod(DexEncodedMethod encodedMethod) {
    if (!encodedMethod.getOptimizationInfo().useIdentifierNameString()) {
      return;
    }
    // Abstract methods do not have code_item.
    if (encodedMethod.shouldNotHaveCode()) {
      return;
    }
    Code code = encodedMethod.getCode();
    if (code == null) {
      return;
    }
    if (code.isDexCode()) {
      Instruction[] instructions = code.asDexCode().instructions;
      for (int i = 0; i < instructions.length; ++i) {
        Instruction instruction = instructions[i];
        if (instruction instanceof DexItemBasedConstString) {
          DexItemBasedConstString cnst = instruction.asDexItemBasedConstString();
          DexString replacement =
              cnst.getClassNameComputationInfo().needsToComputeClassName()
                  ? appInfo.dexItemFactory.createString(
                      computeClassName(
                          lens.lookupDescriptor(cnst.getItem().asDexType()),
                          appInfo.definitionFor(cnst.getItem().asDexType()),
                          cnst.getClassNameComputationInfo()))
                  : lens.lookupName(cnst.getItem(), appInfo.dexItemFactory);
          ConstString constString = new ConstString(cnst.AA, replacement);
          constString.setOffset(instruction.getOffset());
          instructions[i] = constString;
        }
      }
    } else {
      assert code.isCfCode();
      List<CfInstruction> instructions = code.asCfCode().instructions;
      for (int i = 0; i < instructions.size(); ++i) {
        CfInstruction instruction = instructions.get(i);
        if (instruction.isDexItemBasedConstString()) {
          CfDexItemBasedConstString cnst = instruction.asDexItemBasedConstString();
          DexString replacement =
              cnst.getClassNameComputationInfo().needsToComputeClassName()
                  ? appInfo.dexItemFactory.createString(
                      computeClassName(
                          lens.lookupDescriptor(cnst.getItem().asDexType()),
                          appInfo.definitionFor(cnst.getItem().asDexType()),
                          cnst.getClassNameComputationInfo()))
                  : lens.lookupName(cnst.getItem(), appInfo.dexItemFactory);
          instructions.set(i, new CfConstString(replacement));
        }
      }
    }
  }
}
