// 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.code.Const;
import com.android.tools.r8.code.Const16;
import com.android.tools.r8.code.Const4;
import com.android.tools.r8.code.ConstHigh16;
import com.android.tools.r8.code.ConstString;
import com.android.tools.r8.code.ConstStringJumbo;
import com.android.tools.r8.code.ConstWide16;
import com.android.tools.r8.code.ConstWide32;
import com.android.tools.r8.code.FillArrayData;
import com.android.tools.r8.code.FillArrayDataPayload;
import com.android.tools.r8.code.Format35c;
import com.android.tools.r8.code.Format3rc;
import com.android.tools.r8.code.Instruction;
import com.android.tools.r8.code.InvokeDirect;
import com.android.tools.r8.code.InvokeDirectRange;
import com.android.tools.r8.code.InvokeInterface;
import com.android.tools.r8.code.InvokeInterfaceRange;
import com.android.tools.r8.code.InvokeStatic;
import com.android.tools.r8.code.InvokeStaticRange;
import com.android.tools.r8.code.InvokeSuper;
import com.android.tools.r8.code.InvokeSuperRange;
import com.android.tools.r8.code.InvokeVirtual;
import com.android.tools.r8.code.InvokeVirtualRange;
import com.android.tools.r8.code.NewArray;
import com.android.tools.r8.code.Sget;
import com.android.tools.r8.code.SgetBoolean;
import com.android.tools.r8.code.SgetByte;
import com.android.tools.r8.code.SgetChar;
import com.android.tools.r8.code.SgetObject;
import com.android.tools.r8.code.SgetShort;
import com.android.tools.r8.code.SgetWide;
import com.android.tools.r8.dex.ApplicationReader;
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.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.Arrays;
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.
 */
@Deprecated
final public class ResourceShrinker {

  public final static class Command extends BaseCommand {

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

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

  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.
   */
  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);
  }

  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() {
      if (!callback.shouldProcess(classDef.type.getInternalName())) {
        return;
      }

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

      for (DexEncodedMethod method : classDef.allMethodsSorted()) {
        processMethod(method);
      }

      if (classDef.hasAnnotations()) {
        processAnnotations(classDef);
      }
    }

    private void processFieldValue(DexValue value) {
      if (value instanceof DexValue.DexValueString) {
        callback.referencedString(((DexValue.DexValueString) value).value.toString());
      } else if (value instanceof DexValue.DexValueInt) {
        int constantValue = ((DexValue.DexValueInt) value).getValue();
        callback.referencedInt(constantValue);
      } else if (value instanceof DexValue.DexValueArray) {
        DexValue.DexValueArray arrayEncodedValue = (DexValue.DexValueArray) value;
        for (DexValue encodedValue : arrayEncodedValue.getValues()) {
          if (encodedValue instanceof DexValue.DexValueInt) {
            int constantValue = ((DexValue.DexValueInt) encodedValue).getValue();
            callback.referencedInt(constantValue);
          }
        }
      }
    }

    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<FillArrayDataPayload> payloads = Lists.newArrayList();

        Instruction[] instructions = implementation.asDexCode().instructions;
        int current = 0;
        while (current < instructions.length) {
          Instruction 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 FillArrayData) {
            processFillArray(instructions, current, methodIntArrayPayloadOffsets);
          } else if (instruction instanceof FillArrayDataPayload) {
            payloads.add((FillArrayDataPayload) instruction);
          }
          current++;
        }

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

    private void processAnnotations(DexProgramClass classDef) {
      Stream<DexAnnotation> instanceFieldAnnotations =
          Arrays.stream(classDef.instanceFields())
              .filter(DexEncodedField::hasAnnotation)
              .flatMap(f -> Arrays.stream(f.annotations.annotations));
      Stream<DexAnnotation> staticFieldAnnotations =
          Arrays.stream(classDef.staticFields())
              .filter(DexEncodedField::hasAnnotation)
              .flatMap(f -> Arrays.stream(f.annotations.annotations));
      Stream<DexAnnotation> virtualMethodAnnotations =
          Arrays.stream(classDef.virtualMethods())
              .filter(DexEncodedMethod::hasAnnotation)
              .flatMap(m -> Arrays.stream(m.annotations.annotations));
      Stream<DexAnnotation> directMethodAnnotations =
          Arrays.stream(classDef.directMethods())
              .filter(DexEncodedMethod::hasAnnotation)
              .flatMap(m -> Arrays.stream(m.annotations.annotations));
      Stream<DexAnnotation> classAnnotations = Arrays.stream(classDef.annotations.annotations);

      Streams.concat(
          instanceFieldAnnotations,
          staticFieldAnnotations,
          virtualMethodAnnotations,
          directMethodAnnotations,
          classAnnotations)
          .forEach(annotation -> {
            for (DexAnnotationElement element : annotation.annotation.elements) {
              DexValue value = element.value;
              processAnnotationValue(value);
            }
          });
    }

    private void processIntArrayPayload(Instruction instruction) {
      FillArrayDataPayload payload = (FillArrayDataPayload) 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(
        Instruction instruction, Set<Integer> methodIntArrayPayloadOffsets) {
      if (!(instruction instanceof FillArrayDataPayload)) {
        return false;
      }

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

    private void processFillArray(
        Instruction[] instructions, int current, Set<Integer> methodIntArrayPayloadOffsets) {
      FillArrayData fillArrayData = (FillArrayData) instructions[current];
      if (current > 0 && instructions[current - 1] instanceof NewArray) {
        NewArray newArray = (NewArray) 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.offset);
    }

    private void processAnnotationValue(DexValue value) {
      if (value instanceof DexValue.DexValueInt) {
        DexValue.DexValueInt dexValueInt = (DexValue.DexValueInt) value;
        callback.referencedInt(dexValueInt.value);
      } else if (value instanceof DexValue.DexValueString) {
        DexValue.DexValueString dexValueString = (DexValue.DexValueString) value;
        callback.referencedString(dexValueString.value.toString());
      } else if (value instanceof DexValue.DexValueArray) {
        DexValue.DexValueArray dexValueArray = (DexValue.DexValueArray) value;
        for (DexValue dexValue : dexValueArray.getValues()) {
          processAnnotationValue(dexValue);
        }
      } else if (value instanceof DexValue.DexValueAnnotation) {
        DexValue.DexValueAnnotation dexValueAnnotation = (DexValue.DexValueAnnotation) value;
        for (DexAnnotationElement element : dexValueAnnotation.value.elements) {
          processAnnotationValue(element.value);
        }
      }
    }

    private boolean isIntConstInstruction(Instruction instruction) {
      int opcode = instruction.getOpcode();
      return opcode == Const4.OPCODE
          || opcode == Const16.OPCODE
          || opcode == Const.OPCODE
          || opcode == ConstWide32.OPCODE
          || opcode == ConstHigh16.OPCODE
          || opcode == ConstWide16.OPCODE;
    }

    private void processIntConstInstruction(Instruction 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(Instruction instruction) {
      int opcode = instruction.getOpcode();
      return opcode == ConstString.OPCODE || opcode == ConstStringJumbo.OPCODE;
    }

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

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

      callback.referencedString(constantValue);
    }

    private boolean isGetStatic(Instruction instruction) {
      int opcode = instruction.getOpcode();
      return opcode == Sget.OPCODE
          || opcode == SgetBoolean.OPCODE
          || opcode == SgetByte.OPCODE
          || opcode == SgetChar.OPCODE
          || opcode == SgetObject.OPCODE
          || opcode == SgetShort.OPCODE
          || opcode == SgetWide.OPCODE;
    }

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

      DexField field;
      if (instruction instanceof Sget) {
        Sget sget = (Sget) instruction;
        field = sget.getField();
      } else if (instruction instanceof SgetBoolean) {
        SgetBoolean sgetBoolean = (SgetBoolean) instruction;
        field = sgetBoolean.getField();
      } else if (instruction instanceof SgetByte) {
        SgetByte sgetByte = (SgetByte) instruction;
        field = sgetByte.getField();
      } else if (instruction instanceof SgetChar) {
        SgetChar sgetChar = (SgetChar) instruction;
        field = sgetChar.getField();
      } else if (instruction instanceof SgetObject) {
        SgetObject sgetObject = (SgetObject) instruction;
        field = sgetObject.getField();
      } else if (instruction instanceof SgetShort) {
        SgetShort sgetShort = (SgetShort) instruction;
        field = sgetShort.getField();
      } else if (instruction instanceof SgetWide) {
        SgetWide sgetWide = (SgetWide) instruction;
        field = sgetWide.getField();
      } else {
        throw new AssertionError("Not a get static instruction");
      }

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

    private boolean isInvokeInstruction(Instruction instruction) {
      int opcode = instruction.getOpcode();
      return opcode == InvokeVirtual.OPCODE
          || opcode == InvokeSuper.OPCODE
          || opcode == InvokeDirect.OPCODE
          || opcode == InvokeStatic.OPCODE
          || opcode == InvokeInterface.OPCODE;
    }

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

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

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

    private boolean isInvokeRangeInstruction(Instruction instruction) {
      int opcode = instruction.getOpcode();
      return opcode == InvokeVirtualRange.OPCODE
          || opcode == InvokeSuperRange.OPCODE
          || opcode == InvokeDirectRange.OPCODE
          || opcode == InvokeStaticRange.OPCODE
          || opcode == InvokeInterfaceRange.OPCODE;
    }

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

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

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

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