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

import com.android.tools.r8.dex.ApplicationReader;
import com.android.tools.r8.dex.code.DexConst;
import com.android.tools.r8.dex.code.DexConst16;
import com.android.tools.r8.dex.code.DexConst4;
import com.android.tools.r8.dex.code.DexConstHigh16;
import com.android.tools.r8.dex.code.DexConstString;
import com.android.tools.r8.dex.code.DexConstStringJumbo;
import com.android.tools.r8.dex.code.DexConstWide16;
import com.android.tools.r8.dex.code.DexConstWide32;
import com.android.tools.r8.dex.code.DexFillArrayData;
import com.android.tools.r8.dex.code.DexFillArrayDataPayload;
import com.android.tools.r8.dex.code.DexFormat35c;
import com.android.tools.r8.dex.code.DexFormat3rc;
import com.android.tools.r8.dex.code.DexInstruction;
import com.android.tools.r8.dex.code.DexInvokeDirect;
import com.android.tools.r8.dex.code.DexInvokeDirectRange;
import com.android.tools.r8.dex.code.DexInvokeInterface;
import com.android.tools.r8.dex.code.DexInvokeInterfaceRange;
import com.android.tools.r8.dex.code.DexInvokeStatic;
import com.android.tools.r8.dex.code.DexInvokeStaticRange;
import com.android.tools.r8.dex.code.DexInvokeSuper;
import com.android.tools.r8.dex.code.DexInvokeSuperRange;
import com.android.tools.r8.dex.code.DexInvokeVirtual;
import com.android.tools.r8.dex.code.DexInvokeVirtualRange;
import com.android.tools.r8.dex.code.DexNewArray;
import com.android.tools.r8.dex.code.DexSget;
import com.android.tools.r8.dex.code.DexSgetBoolean;
import com.android.tools.r8.dex.code.DexSgetByte;
import com.android.tools.r8.dex.code.DexSgetChar;
import com.android.tools.r8.dex.code.DexSgetObject;
import com.android.tools.r8.dex.code.DexSgetShort;
import com.android.tools.r8.dex.code.DexSgetWide;
import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DexAnnotation;
import com.android.tools.r8.graph.DexAnnotationElement;
import com.android.tools.r8.graph.DexApplication;
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.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexValue;
import com.android.tools.r8.ir.code.SingleConstant;
import com.android.tools.r8.ir.code.WideConstant;
import com.android.tools.r8.keepanno.annotations.KeepForApi;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Timing;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.common.collect.Streams;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.stream.Stream;

/**
 * This class is deprecated and should not be used. It is a temporary solution to use R8 to analyze
 * dex files and compute resource shrinker related bits.
 *
 * <p>Users or this API should implement {@link ReferenceChecker} interface, and through callbacks
 * in that interface, they will be notified when element relevant for resource shrinking is found.
 *
 * <p>This class extracts all integer constants and string constants, which might refer to resource.
 * More specifically, we look for the following while analyzing dex:
 *
 * <ul>
 *   <li>const instructions that might load integers or strings
 *   <li>static fields that have an initial value. This initial value might be integer, string, or
 *       array of integers.
 *   <li>integer array payloads. Only payloads referenced in fill-array-data instructions will be
 *       processed. More specifically, if a payload is referenced in fill-array-data, and we are
 *       able to determine that array is not array of integers, payload will be ignored. Otherwise,
 *       it will be processed once fill-array-data-payload instruction is encountered.
 *   <li>all annotations (class, field, method) that contain annotation element whose value is
 *       integer, string or array of integers are processed.
 * </ul>
 *
 * <p>Please note that switch payloads are not analyzed. Although they might contain integer
 * constants, ones referring to resource ids would have to be loaded in the code analyzed in list
 * above.
 *
 * <p>Usage of this feature is intentionally not supported from the command line.
 */

// TODO(b/121121779) Remove keep if possible.
@Deprecated
@KeepForApi
final public class ResourceShrinker {

  @KeepForApi
  public final static class Command extends BaseCommand {

    Command(AndroidApp app) {
      super(app);
    }

    @Override
    InternalOptions getInternalOptions() {
      return new InternalOptions();
    }
  }

  @KeepForApi
  public final static class Builder extends BaseCommand.Builder<Command, Builder> {

    @Override
    Builder self() {
      return this;
    }

    @Override
    Command makeCommand() {
      return new Command(getAppBuilder().build());
    }
  }

  /**
   * Classes that would like to process data relevant to resource shrinking should implement this
   * interface.
   */
  @KeepForApi
  public interface ReferenceChecker {

    /**
     * Returns if the class with specified internal name should be processed. Typically,
     * resource type classes like R$drawable, R$styleable etc. should be skipped.
     */
    boolean shouldProcess(String internalName);

    void referencedInt(int value);

    void referencedString(String value);

    void referencedStaticField(String internalName, String fieldName);

    void referencedMethod(String internalName, String methodName, String methodDescriptor);

    default void startMethodVisit(MethodReference methodReference) {}

    default void endMethodVisit(MethodReference methodReference) {}

    default void startClassVisit(ClassReference classReference) {}

    default void endClassVisit(ClassReference classReference) {}
  }

  private static final class DexClassUsageVisitor {

    private final DexProgramClass classDef;
    private final ReferenceChecker callback;

    DexClassUsageVisitor(DexProgramClass classDef, ReferenceChecker callback) {
      this.classDef = classDef;
      this.callback = callback;
    }

    public void visit() {
      callback.startClassVisit(classDef.getClassReference());
      if (!callback.shouldProcess(classDef.type.getInternalName())) {
        return;
      }

      for (DexEncodedField field : classDef.staticFields()) {
        DexValue staticValue = field.getStaticValue();
        if (staticValue != null) {
          processFieldValue(staticValue);
        }
      }

      for (DexEncodedMethod method : classDef.allMethodsSorted()) {

        callback.startMethodVisit(method.getReference().asMethodReference());
        processMethod(method);
        callback.endMethodVisit(method.getReference().asMethodReference());
      }

      if (classDef.hasClassOrMemberAnnotations()) {
        processAnnotations(classDef);
      }
      callback.endClassVisit(classDef.getClassReference());
    }

    private void processFieldValue(DexValue value) {
      switch (value.getValueKind()) {
        case ARRAY:
          for (DexValue elementValue : value.asDexValueArray().getValues()) {
            if (elementValue.isDexValueInt()) {
              callback.referencedInt(elementValue.asDexValueInt().getValue());
            }
          }
          break;

        case INT:
          callback.referencedInt(value.asDexValueInt().getValue());
          break;

        case STRING:
          callback.referencedString(value.asDexValueString().value.toString());
          break;

        default:
          // Intentionally empty.
      }
    }

    private void processMethod(DexEncodedMethod method) {
      Code implementation = method.getCode();
      if (implementation != null) {

        // Tracks the offsets of integer array payloads.
        final Set<Integer> methodIntArrayPayloadOffsets = Sets.newHashSet();
        // First we collect payloads, and then we process them because payload can be before the
        // fill-array-data instruction referencing it.
        final List<DexFillArrayDataPayload> payloads = Lists.newArrayList();

        DexInstruction[] instructions = implementation.asDexCode().instructions;
        int current = 0;
        while (current < instructions.length) {
          DexInstruction instruction = instructions[current];
          if (isIntConstInstruction(instruction)) {
            processIntConstInstruction(instruction);
          } else if (isStringConstInstruction(instruction)) {
            processStringConstantInstruction(instruction);
          } else if (isGetStatic(instruction)) {
            processGetStatic(instruction);
          } else if (isInvokeInstruction(instruction)) {
            processInvokeInstruction(instruction);
          } else if (isInvokeRangeInstruction(instruction)) {
            processInvokeRangeInstruction(instruction);
          } else if (instruction instanceof DexFillArrayData) {
            processFillArray(instructions, current, methodIntArrayPayloadOffsets);
          } else if (instruction instanceof DexFillArrayDataPayload) {
            payloads.add((DexFillArrayDataPayload) instruction);
          }
          current++;
        }

        for (DexFillArrayDataPayload payload : payloads) {
          if (isIntArrayPayload(payload, methodIntArrayPayloadOffsets)) {
            processIntArrayPayload(payload);
          }
        }
      }
    }

    private void processAnnotations(DexProgramClass classDef) {
      Stream<DexAnnotation> classAnnotations = classDef.annotations().stream();
      Stream<DexAnnotation> fieldAnnotations =
          Streams.stream(classDef.fields())
              .filter(DexEncodedField::hasAnnotations)
              .flatMap(f -> f.annotations().stream());
      Stream<DexAnnotation> methodAnnotations =
          Streams.stream(classDef.methods())
              .filter(DexEncodedMethod::hasAnyAnnotations)
              .flatMap(m -> m.annotations().stream());

      Streams.concat(classAnnotations, fieldAnnotations, methodAnnotations)
          .forEach(
              annotation -> {
                for (DexAnnotationElement element : annotation.annotation.elements) {
                  DexValue value = element.value;
                  processAnnotationValue(value);
                }
              });
    }

    private void processIntArrayPayload(DexInstruction instruction) {
      DexFillArrayDataPayload payload = (DexFillArrayDataPayload) instruction;

      for (int i = 0; i < payload.data.length / 2; i++) {
        int intValue = payload.data[2 * i + 1] << 16 | payload.data[2 * i];
        callback.referencedInt(intValue);
      }
    }

    private boolean isIntArrayPayload(
        DexInstruction instruction, Set<Integer> methodIntArrayPayloadOffsets) {
      if (!(instruction instanceof DexFillArrayDataPayload)) {
        return false;
      }

      DexFillArrayDataPayload payload = (DexFillArrayDataPayload) instruction;
      return methodIntArrayPayloadOffsets.contains(payload.getOffset());
    }

    private void processFillArray(
        DexInstruction[] instructions, int current, Set<Integer> methodIntArrayPayloadOffsets) {
      DexFillArrayData fillArrayData = (DexFillArrayData) instructions[current];
      if (current > 0 && instructions[current - 1] instanceof DexNewArray) {
        DexNewArray newArray = (DexNewArray) instructions[current - 1];
        if (!Objects.equals(newArray.getType().descriptor.toString(), "[I")) {
          return;
        }
        // Typically, new-array is right before fill-array-data. If not, assume referenced array is
        // of integers. This can be improved later, but for now we make sure no ints are missed.
      }

      methodIntArrayPayloadOffsets.add(
          fillArrayData.getPayloadOffset() + fillArrayData.getOffset());
    }

    private void processAnnotationValue(DexValue value) {
      switch (value.getValueKind()) {
        case ANNOTATION:
          for (DexAnnotationElement element : value.asDexValueAnnotation().value.elements) {
            processAnnotationValue(element.value);
          }
          break;

        case ARRAY:
          for (DexValue elementValue : value.asDexValueArray().getValues()) {
            processAnnotationValue(elementValue);
          }
          break;

        case INT:
          callback.referencedInt(value.asDexValueInt().value);
          break;

        case STRING:
          callback.referencedString(value.asDexValueString().value.toString());
          break;

        default:
          // Intentionally empty.
      }
    }

    private boolean isIntConstInstruction(DexInstruction instruction) {
      int opcode = instruction.getOpcode();
      return opcode == DexConst4.OPCODE
          || opcode == DexConst16.OPCODE
          || opcode == DexConst.OPCODE
          || opcode == DexConstWide32.OPCODE
          || opcode == DexConstHigh16.OPCODE
          || opcode == DexConstWide16.OPCODE;
    }

    private void processIntConstInstruction(DexInstruction instruction) {
      assert isIntConstInstruction(instruction);

      int constantValue;
      if (instruction instanceof SingleConstant) {
        SingleConstant singleConstant = (SingleConstant) instruction;
        constantValue = singleConstant.decodedValue();
      } else if (instruction instanceof WideConstant) {
        WideConstant wideConstant = (WideConstant) instruction;
        if (((int) wideConstant.decodedValue()) != wideConstant.decodedValue()) {
          // We care only about values that fit in int range.
          return;
        }
        constantValue = (int) wideConstant.decodedValue();
      } else {
        throw new AssertionError("Not an int const instruction.");
      }

      callback.referencedInt(constantValue);
    }

    private boolean isStringConstInstruction(DexInstruction instruction) {
      int opcode = instruction.getOpcode();
      return opcode == DexConstString.OPCODE || opcode == DexConstStringJumbo.OPCODE;
    }

    private void processStringConstantInstruction(DexInstruction instruction) {
      assert isStringConstInstruction(instruction);

      String constantValue;
      if (instruction instanceof DexConstString) {
        DexConstString constString = (DexConstString) instruction;
        constantValue = constString.getString().toString();
      } else if (instruction instanceof DexConstStringJumbo) {
        DexConstStringJumbo constStringJumbo = (DexConstStringJumbo) instruction;
        constantValue = constStringJumbo.getString().toString();
      } else {
        throw new AssertionError("Not a string constant instruction.");
      }

      callback.referencedString(constantValue);
    }

    private boolean isGetStatic(DexInstruction instruction) {
      int opcode = instruction.getOpcode();
      return opcode == DexSget.OPCODE
          || opcode == DexSgetBoolean.OPCODE
          || opcode == DexSgetByte.OPCODE
          || opcode == DexSgetChar.OPCODE
          || opcode == DexSgetObject.OPCODE
          || opcode == DexSgetShort.OPCODE
          || opcode == DexSgetWide.OPCODE;
    }

    private void processGetStatic(DexInstruction instruction) {
      assert isGetStatic(instruction);

      DexField field;
      if (instruction instanceof DexSget) {
        DexSget sget = (DexSget) instruction;
        field = sget.getField();
      } else if (instruction instanceof DexSgetBoolean) {
        DexSgetBoolean sgetBoolean = (DexSgetBoolean) instruction;
        field = sgetBoolean.getField();
      } else if (instruction instanceof DexSgetByte) {
        DexSgetByte sgetByte = (DexSgetByte) instruction;
        field = sgetByte.getField();
      } else if (instruction instanceof DexSgetChar) {
        DexSgetChar sgetChar = (DexSgetChar) instruction;
        field = sgetChar.getField();
      } else if (instruction instanceof DexSgetObject) {
        DexSgetObject sgetObject = (DexSgetObject) instruction;
        field = sgetObject.getField();
      } else if (instruction instanceof DexSgetShort) {
        DexSgetShort sgetShort = (DexSgetShort) instruction;
        field = sgetShort.getField();
      } else if (instruction instanceof DexSgetWide) {
        DexSgetWide sgetWide = (DexSgetWide) instruction;
        field = sgetWide.getField();
      } else {
        throw new AssertionError("Not a get static instruction");
      }

      callback.referencedStaticField(field.holder.getInternalName(), field.name.toString());
    }

    private boolean isInvokeInstruction(DexInstruction instruction) {
      int opcode = instruction.getOpcode();
      return opcode == DexInvokeVirtual.OPCODE
          || opcode == DexInvokeSuper.OPCODE
          || opcode == DexInvokeDirect.OPCODE
          || opcode == DexInvokeStatic.OPCODE
          || opcode == DexInvokeInterface.OPCODE;
    }

    private void processInvokeInstruction(DexInstruction instruction) {
      assert isInvokeInstruction(instruction);

      DexFormat35c ins35c = (DexFormat35c) instruction;
      DexMethod method = (DexMethod) ins35c.BBBB;

      callback.referencedMethod(
          method.holder.getInternalName(),
          method.name.toString(),
          method.proto.toDescriptorString());
    }

    private boolean isInvokeRangeInstruction(DexInstruction instruction) {
      int opcode = instruction.getOpcode();
      return opcode == DexInvokeVirtualRange.OPCODE
          || opcode == DexInvokeSuperRange.OPCODE
          || opcode == DexInvokeDirectRange.OPCODE
          || opcode == DexInvokeStaticRange.OPCODE
          || opcode == DexInvokeInterfaceRange.OPCODE;
    }

    private void processInvokeRangeInstruction(DexInstruction instruction) {
      assert isInvokeRangeInstruction(instruction);

      DexFormat3rc ins3rc = (DexFormat3rc) instruction;
      DexMethod method = (DexMethod) ins3rc.BBBB;

      callback.referencedMethod(
          method.holder.getInternalName(),
          method.name.toString(),
          method.proto.toDescriptorString());
    }
  }

  @SuppressWarnings("RedundantThrows")
  public static void run(Command command, ReferenceChecker callback)
      throws IOException, ExecutionException {
    runForTesting(command.getInputApp(), command.getInternalOptions(), callback);
  }

  public static void runForTesting(
      AndroidApp inputApp, InternalOptions options, ReferenceChecker callback)
      throws IOException, ExecutionException {
    Timing timing = new Timing("resource shrinker analyzer");
    DexApplication dexApplication = new ApplicationReader(inputApp, options, timing).read();
    for (DexProgramClass programClass : dexApplication.classes()) {
      new DexClassUsageVisitor(programClass, callback).visit();
    }
  }
}
