// Copyright (c) 2021, 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.shaking;

import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
import static com.android.tools.r8.utils.MapUtils.ignoreKey;

import com.android.tools.r8.graph.DexDefinitionSupplier;
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.DexReference;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.ProgramDefinition;
import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.PrunedItems;
import com.android.tools.r8.shaking.KeepInfo.Joiner;
import com.android.tools.r8.utils.MapUtils;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;
import java.util.function.BiPredicate;
import java.util.function.Predicate;

public class MinimumKeepInfoCollection {

  private static final MinimumKeepInfoCollection EMPTY =
      new MinimumKeepInfoCollection(Collections.emptyMap());

  private final Map<DexReference, KeepInfo.Joiner<?, ?, ?>> minimumKeepInfo;

  public MinimumKeepInfoCollection() {
    this(new ConcurrentHashMap<>());
  }

  private MinimumKeepInfoCollection(Map<DexReference, KeepInfo.Joiner<?, ?, ?>> minimumKeepInfo) {
    this.minimumKeepInfo = minimumKeepInfo;
  }

  public static MinimumKeepInfoCollection empty() {
    return EMPTY;
  }

  public void forEach(BiConsumer<DexReference, KeepInfo.Joiner<?, ?, ?>> consumer) {
    minimumKeepInfo.forEach(consumer);
  }

  public void forEach(
      DexDefinitionSupplier definitions,
      BiConsumer<DexProgramClass, KeepClassInfo.Joiner> classConsumer,
      BiConsumer<ProgramField, KeepFieldInfo.Joiner> fieldConsumer,
      BiConsumer<ProgramMethod, KeepMethodInfo.Joiner> methodConsumer) {
    minimumKeepInfo.forEach(
        (reference, joiner) -> {
          DexProgramClass contextClass =
              asProgramClassOrNull(definitions.definitionFor(reference.getContextType()));
          if (contextClass != null) {
            reference.accept(
                clazz -> classConsumer.accept(contextClass, joiner.asClassJoiner()),
                fieldReference -> {
                  ProgramField field = contextClass.lookupProgramField(fieldReference);
                  if (field != null) {
                    fieldConsumer.accept(field, joiner.asFieldJoiner());
                  }
                },
                methodReference -> {
                  ProgramMethod method = contextClass.lookupProgramMethod(methodReference);
                  if (method != null) {
                    methodConsumer.accept(method, joiner.asMethodJoiner());
                  }
                });
          }
        });
  }

  @SuppressWarnings("unchecked")
  public <T extends DexReference> void forEachThatMatches(
      BiPredicate<DexReference, Joiner<?, ?, ?>> predicate,
      BiConsumer<T, KeepInfo.Joiner<?, ?, ?>> consumer) {
    minimumKeepInfo.forEach(
        (reference, minimumKeepInfoForReference) -> {
          if (predicate.test(reference, minimumKeepInfoForReference)) {
            consumer.accept((T) reference, minimumKeepInfoForReference);
          }
        });
  }

  public KeepInfo.Joiner<?, ?, ?> getOrDefault(
      DexReference reference, KeepInfo.Joiner<?, ?, ?> defaultValue) {
    return minimumKeepInfo.getOrDefault(reference, defaultValue);
  }

  public KeepInfo.Joiner<?, ?, ?> getOrCreateMinimumKeepInfoFor(DexReference reference) {
    return minimumKeepInfo.computeIfAbsent(
        reference, ignoreKey(() -> KeepInfo.newEmptyJoinerFor(reference)));
  }

  public boolean hasMinimumKeepInfoThatMatches(
      DexReference reference, Predicate<KeepInfo.Joiner<?, ?, ?>> predicate) {
    KeepInfo.Joiner<?, ?, ?> minimumKeepInfoForReference = minimumKeepInfo.get(reference);
    return minimumKeepInfoForReference != null && predicate.test(minimumKeepInfoForReference);
  }

  public boolean isEmpty() {
    return minimumKeepInfo.isEmpty();
  }

  public void merge(MinimumKeepInfoCollection otherMinimumKeepInfo) {
    otherMinimumKeepInfo.forEach(this::mergeMinimumKeepInfoFor);
  }

  public void mergeMinimumKeepInfoFor(
      DexReference reference, KeepInfo.Joiner<?, ?, ?> minimumKeepInfoForReference) {
    getOrCreateMinimumKeepInfoFor(reference).mergeUnsafe(minimumKeepInfoForReference);
  }

  public void pruneDeadItems(DexDefinitionSupplier definitions, Enqueuer enqueuer) {
    MapUtils.removeIf(
        minimumKeepInfo,
        (reference, minimumKeepInfoForReference) -> {
          assert !minimumKeepInfoForReference.isBottom();
          ProgramDefinition definition =
              reference.apply(
                  clazz -> asProgramClassOrNull(definitions.definitionFor(clazz)),
                  field ->
                      field.lookupOnProgramClass(
                          asProgramClassOrNull(definitions.definitionFor(field.getHolderType()))),
                  method ->
                      method.lookupOnProgramClass(
                          asProgramClassOrNull(definitions.definitionFor(method.getHolderType()))));
          return definition == null || !enqueuer.isReachable(definition);
        });
  }

  public void pruneItems(PrunedItems prunedItems) {
    minimumKeepInfo.keySet().removeIf(prunedItems::isRemoved);
  }

  public KeepClassInfo.Joiner remove(DexType clazz) {
    return (KeepClassInfo.Joiner) minimumKeepInfo.remove(clazz);
  }

  public KeepFieldInfo.Joiner remove(DexField field) {
    return (KeepFieldInfo.Joiner) minimumKeepInfo.remove(field);
  }

  public KeepMethodInfo.Joiner remove(DexMethod method) {
    return (KeepMethodInfo.Joiner) minimumKeepInfo.remove(method);
  }

  public MinimumKeepInfoCollection rewrittenWithLens(GraphLens graphLens) {
    MinimumKeepInfoCollection rewrittenMinimumKeepInfo = new MinimumKeepInfoCollection();
    forEach(
        (reference, minimumKeepInfoForReference) -> {
          DexReference rewrittenReference =
              reference.apply(
                  type -> {
                    DexType rewrittenType = graphLens.lookupType(type);
                    if (rewrittenType.isPrimitiveType()) {
                      // May happen due to enum unboxing.
                      assert type.isClassType();
                      assert rewrittenType.isIntType();
                      return null;
                    }
                    return rewrittenType;
                  },
                  graphLens::getRenamedFieldSignature,
                  graphLens::getRenamedMethodSignature);
          if (rewrittenReference != null) {
            rewrittenMinimumKeepInfo
                .getOrCreateMinimumKeepInfoFor(rewrittenReference)
                .mergeUnsafe(minimumKeepInfoForReference);
          }
        });
    return rewrittenMinimumKeepInfo;
  }
}
