// Copyright (c) 2019, 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.utils.codeinspector.analysis;

import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FieldSubject;
import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
import com.android.tools.r8.utils.codeinspector.FoundFieldSubject;
import com.android.tools.r8.utils.codeinspector.FoundMethodSubject;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
import com.google.common.collect.Sets;
import java.util.Set;
import java.util.function.Function;

public class ProtoApplicationStats {

  private static final String EXTENDABLE_MESSAGE_TYPE =
      "com.google.protobuf.GeneratedMessageLite$ExtendableMessage";
  private static final String EXTENSION_REGISTRY_LITE_TYPE =
      "com.google.protobuf.ExtensionRegistryLite";
  private static final String GENERATED_EXTENSION_TYPE =
      "com.google.protobuf.GeneratedMessageLite$GeneratedExtension";
  private static final String GENERATED_MESSAGE_LITE_TYPE =
      "com.google.protobuf.GeneratedMessageLite";
  private static final String GENERATED_MESSAGE_LITE_BUILDER_TYPE =
      GENERATED_MESSAGE_LITE_TYPE + "$Builder";
  private static final String GENERATED_MESSAGE_LITE_EXTENDABLE_BUILDER_TYPE =
      GENERATED_MESSAGE_LITE_TYPE + "$ExtendableBuilder";

  abstract static class Stats {

    static <T> String progress(T actual, T baseline, T original, Function<T, Set<?>> fn) {
      StringBuilder builder = new StringBuilder();
      if (original != null) {
        builder.append(fn.apply(original).size()).append(" -> ");
      }
      Set<?> actualSet = fn.apply(actual);
      builder.append(actualSet.size());
      if (baseline != null) {
        Set<?> baselineSet = fn.apply(baseline);
        builder
            .append(" (unfulfilled potential: ")
            .append(Sets.difference(actualSet, baselineSet).size())
            .append(", improvement over baseline: ")
            .append(Sets.difference(baselineSet, actualSet).size())
            .append(" )");
      }
      return builder.toString();
    }
  }

  class EnumStats extends Stats {

    final Set<DexType> enums = Sets.newIdentityHashSet();

    String getStats(EnumStats baseline, EnumStats original) {
      return StringUtils.lines(
          "Enum stats:", "  # enums: " + progress(this, baseline, original, x -> x.enums));
    }
  }

  class ProtoBuilderStats extends Stats {

    final Set<DexType> builders = Sets.newIdentityHashSet();

    String getStats(ProtoBuilderStats baseline, ProtoBuilderStats original) {
      return StringUtils.lines(
          "Proto builder stats:",
          "  # builders: " + progress(this, baseline, original, x -> x.builders));
    }
  }

  class ProtoMessageStats extends Stats {

    final boolean extendable;

    ProtoMessageStats(boolean extendable) {
      this.extendable = extendable;
    }

    final Set<DexType> messages = Sets.newIdentityHashSet();
    final Set<DexField> bitFields = Sets.newIdentityHashSet();
    final Set<DexField> nonBitFields = Sets.newIdentityHashSet();

    String getStats(ProtoMessageStats baseline, ProtoMessageStats original) {
      return StringUtils.lines(
          extendable ? "Extendable proto message stats" : "Proto message stats:",
          "  # messages: " + progress(this, baseline, original, x -> x.messages),
          "  # bit fields: " + progress(this, baseline, original, x -> x.bitFields),
          "  # non-bit fields: " + progress(this, baseline, original, x -> x.nonBitFields));
    }
  }

  public class GeneratedExtensionRegistryStats extends Stats {

    final Set<DexMethod> findLiteExtensionByNumberMethods = Sets.newIdentityHashSet();
    final Set<DexField> retainedExtensionFields = Sets.newIdentityHashSet();
    final Set<DexField> spuriouslyRetainedExtensionFields = Sets.newIdentityHashSet();

    public Set<DexField> getSpuriouslyRetainedExtensionFields() {
      return spuriouslyRetainedExtensionFields;
    }

    String getStats(
        GeneratedExtensionRegistryStats baseline, GeneratedExtensionRegistryStats original) {
      return StringUtils.lines(
          "Generated extension registry stats:",
          "  # findLiteExtensionByNumber() methods: "
              + progress(this, baseline, original, x -> x.findLiteExtensionByNumberMethods),
          "  # retained extensions: "
              + progress(this, baseline, original, x -> x.retainedExtensionFields),
          "  # spuriously retained extension fields: " + spuriouslyRetainedExtensionFields.size());
    }
  }

  private final DexItemFactory dexItemFactory;
  private final CodeInspector inspector;
  private final ProtoApplicationStats original;

  private final EnumStats enumStats = new EnumStats();
  private final ProtoMessageStats extendableProtoMessageStats = new ProtoMessageStats(true);
  private final GeneratedExtensionRegistryStats generatedExtensionRegistryStats =
      new GeneratedExtensionRegistryStats();
  private final ProtoBuilderStats protoBuilderStats = new ProtoBuilderStats();
  private final ProtoMessageStats protoMessageStats = new ProtoMessageStats(false);

  public ProtoApplicationStats(DexItemFactory dexItemFactory, CodeInspector inspector) {
    this(dexItemFactory, inspector, null);
  }

  public ProtoApplicationStats(
      DexItemFactory dexItemFactory, CodeInspector inspector, ProtoApplicationStats original) {
    this.dexItemFactory = dexItemFactory;
    this.inspector = inspector;
    this.original = original;
    computeStats();
  }

  private void computeStats() {
    for (FoundClassSubject classSubject : inspector.allClasses()) {
      DexType originalType = classSubject.getOriginalDexType(dexItemFactory);
      if (classSubject.getDexClass().isEnum()) {
        enumStats.enums.add(originalType);
      }

      ClassSubject superClassSubject = classSubject.getSuperClass();
      if (!superClassSubject.isPresent()) {
        continue;
      }

      ProtoMessageStats messageStats = null;
      switch (superClassSubject.getOriginalName()) {
        case GENERATED_MESSAGE_LITE_TYPE:
          messageStats = protoMessageStats;
          break;

        case EXTENDABLE_MESSAGE_TYPE:
          messageStats = extendableProtoMessageStats;
          break;

        case GENERATED_MESSAGE_LITE_BUILDER_TYPE:
        case GENERATED_MESSAGE_LITE_EXTENDABLE_BUILDER_TYPE:
          protoBuilderStats.builders.add(
              dexItemFactory.createType(classSubject.getOriginalDescriptor()));
          break;

        case EXTENSION_REGISTRY_LITE_TYPE:
          for (FoundMethodSubject methodSubject : classSubject.allMethods()) {
            String originalMethodName = methodSubject.getOriginalName(false);
            if (originalMethodName.startsWith("findLiteExtensionByNumber")) {
              generatedExtensionRegistryStats.findLiteExtensionByNumberMethods.add(
                  methodSubject.getOriginalDexMethod(dexItemFactory));

              for (InstructionSubject instruction :
                  methodSubject.instructions(InstructionSubject::isStaticGet)) {
                DexField field = instruction.getField();
                FoundClassSubject typeClassSubject =
                    inspector.clazz(field.type.toSourceString()).asFoundClassSubject();
                if (!typeClassSubject.getOriginalName().equals(GENERATED_EXTENSION_TYPE)) {
                  continue;
                }
                FoundClassSubject extensionClassSubject =
                    inspector.clazz(field.holder.toSourceString()).asFoundClassSubject();
                FoundFieldSubject extensionFieldSubject =
                    extensionClassSubject
                        .uniqueFieldWithFinalName(field.name.toSourceString())
                        .asFoundFieldSubject();
                generatedExtensionRegistryStats.retainedExtensionFields.add(
                    extensionFieldSubject.getOriginalDexField(dexItemFactory));
              }
            }
          }
          break;
      }

      if (messageStats != null) {
        messageStats.messages.add(originalType);
        for (FoundFieldSubject fieldSubject : classSubject.allInstanceFields()) {
          String originalFieldName = fieldSubject.getOriginalName(false);
          if (originalFieldName.startsWith("bitField")) {
            messageStats.bitFields.add(fieldSubject.getOriginalDexField(dexItemFactory));
          } else {
            messageStats.nonBitFields.add(fieldSubject.getOriginalDexField(dexItemFactory));
          }
        }
      }
    }

    if (original != null) {
      for (DexField extensionField :
          original.generatedExtensionRegistryStats.retainedExtensionFields) {
        if (generatedExtensionRegistryStats.retainedExtensionFields.contains(extensionField)) {
          continue;
        }
        ClassSubject classSubject = inspector.clazz(extensionField.holder.toSourceString());
        if (!classSubject.isPresent()) {
          continue;
        }
        FieldSubject fieldSubject =
            classSubject.uniqueFieldWithName(extensionField.name.toSourceString());
        if (fieldSubject.isPresent()) {
          generatedExtensionRegistryStats.spuriouslyRetainedExtensionFields.add(extensionField);
        }
      }
    }
  }

  public GeneratedExtensionRegistryStats getGeneratedExtensionRegistryStats() {
    return generatedExtensionRegistryStats;
  }

  public String getStats() {
    return StringUtils.lines(
        enumStats.getStats(null, original.enumStats),
        protoMessageStats.getStats(null, original.protoMessageStats),
        extendableProtoMessageStats.getStats(null, original.extendableProtoMessageStats),
        protoBuilderStats.getStats(null, original.protoBuilderStats),
        generatedExtensionRegistryStats.getStats(null, original.generatedExtensionRegistryStats));
  }

  public String getStats(ProtoApplicationStats baseline) {
    return StringUtils.lines(
        enumStats.getStats(baseline.enumStats, original.enumStats),
        protoMessageStats.getStats(baseline.protoMessageStats, original.protoMessageStats),
        extendableProtoMessageStats.getStats(
            baseline.extendableProtoMessageStats, original.extendableProtoMessageStats),
        protoBuilderStats.getStats(baseline.protoBuilderStats, original.protoBuilderStats),
        generatedExtensionRegistryStats.getStats(
            baseline.generatedExtensionRegistryStats, original.generatedExtensionRegistryStats));
  }
}
