// 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.shaking.KeepInfo.Joiner;
import com.android.tools.r8.utils.MapUtils;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Map;
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 IdentityHashMap<>());
  }

  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<?, ?, ?> 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 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;
  }
}
