// 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.utils.DescriptorUtils.descriptorToJavaType;

import com.android.tools.r8.code.ConstString;
import com.android.tools.r8.code.ConstStringJumbo;
import com.android.tools.r8.code.Instruction;
import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItem;
import com.android.tools.r8.graph.DexItemBasedString;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
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.DexValueString;
import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import com.android.tools.r8.shaking.ProguardClassFilter;
import java.util.Map;
import java.util.Set;

class IdentifierMinifier {

  private final AppInfoWithLiveness appInfo;
  private final ProguardClassFilter adaptClassStrings;
  private final NamingLens lens;
  private final Set<DexItem> identifierNameStrings;

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

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

  private void adaptClassStrings() {
    for (DexProgramClass clazz : appInfo.classes()) {
      if (!adaptClassStrings.matches(clazz.type)) {
        continue;
      }
      clazz.forEachField(this::adaptClassStringsInField);
      clazz.forEachMethod(this::adaptClassStringsInMethod);
    }
  }

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

  private void adaptClassStringsInMethod(DexEncodedMethod encodedMethod) {
    // Abstract methods do not have code_item.
    if (encodedMethod.accessFlags.isAbstract()) {
      return;
    }
    Code code = encodedMethod.getCode();
    if (code == null) {
      return;
    }
    assert code.isDexCode();
    DexCode dexCode = code.asDexCode();
    for (Instruction instr : dexCode.instructions) {
      if (instr instanceof ConstString) {
        ConstString cnst = (ConstString) instr;
        DexString dexString = cnst.getString();
        cnst.BBBB = getRenamedStringLiteral(dexString);
      } else if (instr instanceof ConstStringJumbo) {
        ConstStringJumbo cnst = (ConstStringJumbo) instr;
        DexString dexString = cnst.getString();
        cnst.BBBBBBBB = getRenamedStringLiteral(dexString);
      }
    }
  }

  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 replaceIdentifierNameString() {
    for (DexProgramClass clazz : appInfo.classes()) {
      // Some const strings could be moved to field's static value (from <clinit>).
      clazz.forEachField(this::replaceIdentifierNameStringInField);
      clazz.forEachMethod(this::replaceIdentifierNameStringInMethod);
    }
  }

  private void replaceIdentifierNameStringInField(DexEncodedField encodedField) {
    if (!encodedField.accessFlags.isStatic()) {
      return;
    }
    DexValue staticValue = encodedField.getStaticValue();
    if (!(staticValue instanceof DexValueString)) {
      return;
    }
    DexString original = ((DexValueString) staticValue).getValue();
    if (original instanceof DexItemBasedString) {
      encodedField.setStaticValue(new DexValueString(materialize((DexItemBasedString) original)));
    }
  }

  private void replaceIdentifierNameStringInMethod(DexEncodedMethod encodedMethod) {
    if (!encodedMethod.getOptimizationInfo().useIdentifierNameString()) {
      return;
    }
    // Abstract methods do not have code_item.
    if (encodedMethod.accessFlags.isAbstract()) {
      return;
    }
    Code code = encodedMethod.getCode();
    if (code == null) {
      return;
    }
    assert code.isDexCode();
    DexCode dexCode = code.asDexCode();
    for (Instruction instr : dexCode.instructions) {
      if (instr instanceof ConstString
          && ((ConstString) instr).getString() instanceof DexItemBasedString) {
        ConstString cnst = (ConstString) instr;
        DexItemBasedString itemBasedString = (DexItemBasedString) cnst.getString();
        cnst.BBBB = materialize(itemBasedString);
      } else if (instr instanceof ConstStringJumbo
          && ((ConstStringJumbo) instr).getString() instanceof DexItemBasedString) {
        ConstStringJumbo cnst = (ConstStringJumbo) instr;
        DexItemBasedString itemBasedString = (DexItemBasedString) cnst.getString();
        cnst.BBBBBBBB = materialize(itemBasedString);
      }
    }
  }

  private DexString materialize(DexItemBasedString itemBasedString) {
    if (itemBasedString.basedOn instanceof DexType) {
      DexString renamed = lens.lookupDescriptor((DexType) itemBasedString.basedOn);
      if (!renamed.toString().equals(itemBasedString.toString())) {
        return appInfo.dexItemFactory.createString(descriptorToJavaType(renamed.toString()));
      }
      return renamed;
    } else if (itemBasedString.basedOn instanceof DexMethod) {
      return lens.lookupName((DexMethod) itemBasedString.basedOn);
    } else {
      assert itemBasedString.basedOn instanceof DexField;
      return lens.lookupName((DexField) itemBasedString.basedOn);
    }
  }

}
