package com.android.tools.r8.graph;

import static com.google.common.base.Predicates.alwaysTrue;

import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.IterableUtils;
import com.android.tools.r8.utils.TraversalContinuation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

public class MethodCollection {

  @FunctionalInterface
  public interface MethodCollectionFactory {

    MethodCollection create(DexClass holder);

    static MethodCollectionFactory empty() {
      return fromMethods(DexEncodedMethod.EMPTY_ARRAY, DexEncodedMethod.EMPTY_ARRAY);
    }

    static MethodCollectionFactory fromMethods(
        DexEncodedMethod[] directs, DexEncodedMethod[] virtuals) {
      return holder -> MethodCollection.create(holder, directs, virtuals);
    }
  }

  // Threshold between using an array and a map for the backing store.
  // Compiling R8 plus library shows classes with up to 30 methods account for about 95% of classes.
  private static final int ARRAY_BACKING_THRESHOLD = 30;

  private final DexClass holder;
  private MethodCollectionBacking backing;
  private DexEncodedMethod cachedClassInitializer = DexEncodedMethod.SENTINEL;

  /** Should only be called via 'createInternal' (and the concurrency checking subtype). */
  MethodCollection(DexClass holder, MethodCollectionBacking backing) {
    this.holder = holder;
    this.backing = backing;
  }

  public static MethodCollection create(
      DexClass holder, DexEncodedMethod[] directMethods, DexEncodedMethod[] virtualMethods) {
    int methodCount = directMethods.length + virtualMethods.length;
    MethodCollectionBacking backing;
    if (methodCount > ARRAY_BACKING_THRESHOLD) {
      backing = MethodMapBacking.createLinked(methodCount);
      backing.setDirectMethods(directMethods);
      backing.setVirtualMethods(virtualMethods);
    } else {
      backing = MethodArrayBacking.fromArrays(directMethods, virtualMethods);
    }
    return createInternal(holder, backing);
  }

  private static MethodCollection createInternal(DexClass holder, MethodCollectionBacking backing) {
    return InternalOptions.USE_METHOD_COLLECTION_CONCURRENCY_CHECKED
        ? new MethodCollectionConcurrencyChecked(holder, backing)
        : new MethodCollection(holder, backing);
  }

  public MethodCollection fixup(
      DexClass newHolder, Function<DexEncodedMethod, DexEncodedMethod> fn) {
    MethodCollectionBacking newBacking = backing.map(fn);
    return createInternal(newHolder, newBacking);
  }

  private void resetCaches() {
    resetDirectMethodCaches();
    resetVirtualMethodCaches();
  }

  private void resetDirectMethodCaches() {
    resetClassInitializerCache();
  }

  private void resetVirtualMethodCaches() {
    // Nothing to do.
  }

  public boolean hasMethods(Predicate<DexEncodedMethod> predicate) {
    return getMethod(predicate) != null;
  }

  public boolean hasDirectMethods() {
    return hasDirectMethods(alwaysTrue());
  }

  public boolean hasDirectMethods(Predicate<DexEncodedMethod> predicate) {
    return backing.getDirectMethod(predicate) != null;
  }

  public boolean hasVirtualMethods() {
    return hasVirtualMethods(alwaysTrue());
  }

  public boolean hasVirtualMethods(Predicate<DexEncodedMethod> predicate) {
    return backing.getVirtualMethod(predicate) != null;
  }

  public int numberOfDirectMethods() {
    return backing.numberOfDirectMethods();
  }

  public int numberOfVirtualMethods() {
    return backing.numberOfVirtualMethods();
  }

  public int size() {
    return backing.size();
  }

  public TraversalContinuation<?> traverse(
      Function<DexEncodedMethod, TraversalContinuation<?>> fn) {
    return backing.traverse(fn);
  }

  public void forEachMethod(Consumer<DexEncodedMethod> consumer) {
    forEachMethodMatching(alwaysTrue(), consumer);
  }

  public void forEachMethodMatching(
      Predicate<DexEncodedMethod> predicate, Consumer<DexEncodedMethod> consumer) {
    backing.forEachMethod(
        method -> {
          if (predicate.test(method)) {
            consumer.accept(method);
          }
        });
  }

  public void forEachDirectMethod(Consumer<DexEncodedMethod> consumer) {
    forEachDirectMethodMatching(alwaysTrue(), consumer);
  }

  public void forEachDirectMethodMatching(
      Predicate<DexEncodedMethod> predicate, Consumer<DexEncodedMethod> consumer) {
    backing.forEachDirectMethod(
        method -> {
          if (predicate.test(method)) {
            consumer.accept(method);
          }
        });
  }

  public void forEachVirtualMethod(Consumer<DexEncodedMethod> consumer) {
    forEachVirtualMethodMatching(alwaysTrue(), consumer);
  }

  public void forEachVirtualMethodMatching(
      Predicate<DexEncodedMethod> predicate, Consumer<DexEncodedMethod> consumer) {
    backing.forEachVirtualMethod(
        method -> {
          if (predicate.test(method)) {
            consumer.accept(method);
          }
        });
  }

  public Iterable<DexEncodedMethod> methods() {
    return backing.methods();
  }

  public Iterable<DexEncodedMethod> methods(Predicate<? super DexEncodedMethod> predicate) {
    return IterableUtils.filter(methods(), predicate);
  }

  public List<DexEncodedMethod> allMethodsSorted() {
    List<DexEncodedMethod> sorted = new ArrayList<>(size());
    forEachMethod(sorted::add);
    sorted.sort(Comparator.comparing(DexEncodedMember::getReference));
    return sorted;
  }

  public Iterable<DexEncodedMethod> directMethods() {
    return backing.directMethods();
  }

  public Iterable<DexEncodedMethod> virtualMethods() {
    return backing.virtualMethods();
  }

  public DexEncodedMethod getMethod(DexMethod method) {
    return backing.getMethod(method.getProto(), method.getName());
  }

  public DexEncodedMethod getMethod(DexProto methodProto, DexString methodName) {
    return backing.getMethod(methodProto, methodName);
  }

  public final DexEncodedMethod getMethod(DexMethodSignature method) {
    return getMethod(method.getProto(), method.getName());
  }

  public DexEncodedMethod getMethod(Predicate<DexEncodedMethod> predicate) {
    DexEncodedMethod result = backing.getDirectMethod(predicate);
    return result != null ? result : backing.getVirtualMethod(predicate);
  }

  public DexEncodedMethod getDirectMethod(DexMethod method) {
    return backing.getDirectMethod(method);
  }

  public DexEncodedMethod getDirectMethod(Predicate<DexEncodedMethod> predicate) {
    return backing.getDirectMethod(predicate);
  }

  public DexEncodedMethod getVirtualMethod(DexMethod method) {
    return backing.getVirtualMethod(method);
  }

  public DexEncodedMethod getVirtualMethod(Predicate<DexEncodedMethod> predicate) {
    return backing.getVirtualMethod(predicate);
  }

  private void resetClassInitializerCache() {
    cachedClassInitializer = DexEncodedMethod.SENTINEL;
  }

  public synchronized DexEncodedMethod getClassInitializer() {
    if (cachedClassInitializer == DexEncodedMethod.SENTINEL) {
      cachedClassInitializer = null;
      for (DexEncodedMethod directMethod : directMethods()) {
        if (directMethod.isClassInitializer()) {
          cachedClassInitializer = directMethod;
          break;
        }
      }
    }
    return cachedClassInitializer;
  }

  public void addMethod(DexEncodedMethod method) {
    resetCaches();
    backing.addMethod(method);
  }

  public void addVirtualMethod(DexEncodedMethod virtualMethod) {
    resetVirtualMethodCaches();
    backing.addVirtualMethod(virtualMethod);
  }

  public void addDirectMethod(DexEncodedMethod directMethod) {
    resetDirectMethodCaches();
    backing.addDirectMethod(directMethod);
  }

  public DexEncodedMethod replaceDirectMethod(
      DexMethod method, Function<DexEncodedMethod, DexEncodedMethod> replacement) {
    resetDirectMethodCaches();
    return backing.replaceDirectMethod(method, replacement);
  }

  public DexEncodedMethod replaceVirtualMethod(
      DexMethod method, Function<DexEncodedMethod, DexEncodedMethod> replacement) {
    resetVirtualMethodCaches();
    return backing.replaceVirtualMethod(method, replacement);
  }

  public void replaceMethods(Function<DexEncodedMethod, DexEncodedMethod> replacement) {
    resetCaches();
    backing.replaceMethods(replacement);
  }

  public void replaceDirectMethods(Function<DexEncodedMethod, DexEncodedMethod> replacement) {
    resetDirectMethodCaches();
    backing.replaceDirectMethods(replacement);
  }

  public void replaceVirtualMethods(Function<DexEncodedMethod, DexEncodedMethod> replacement) {
    resetVirtualMethodCaches();
    backing.replaceVirtualMethods(replacement);
  }

  public void replaceAllDirectMethods(Function<DexEncodedMethod, DexEncodedMethod> replacement) {
    resetDirectMethodCaches();
    backing.replaceAllDirectMethods(replacement);
  }

  public void replaceAllVirtualMethods(Function<DexEncodedMethod, DexEncodedMethod> replacement) {
    resetVirtualMethodCaches();
    backing.replaceAllVirtualMethods(replacement);
  }

  /**
   * Replace a direct method, if found, by a computed virtual method using the replacement function.
   *
   * @param method Direct method to replace if present.
   * @param replacement Replacement function computing the virtual replacement.
   * @return Returns the replacement if found, null otherwise.
   */
  public DexEncodedMethod replaceDirectMethodWithVirtualMethod(
      DexMethod method, Function<DexEncodedMethod, DexEncodedMethod> replacement) {
    resetCaches();
    return backing.replaceDirectMethodWithVirtualMethod(method, replacement);
  }

  public void addDirectMethods(Collection<DexEncodedMethod> methods) {
    assert verifyCorrectnessOfMethodHolders(methods);
    resetDirectMethodCaches();
    backing.addDirectMethods(methods);
  }

  public void clearDirectMethods() {
    resetDirectMethodCaches();
    backing.clearDirectMethods();
  }

  public DexEncodedMethod removeMethod(DexMethod method) {
    DexEncodedMethod removed = backing.removeMethod(method);
    if (removed != null) {
      if (backing.belongsToDirectPool(removed)) {
        resetDirectMethodCaches();
      } else {
        assert backing.belongsToVirtualPool(removed);
        resetVirtualMethodCaches();
      }
    }
    return removed;
  }

  public void removeMethods(Set<DexEncodedMethod> methods) {
    backing.removeMethods(methods);
    resetDirectMethodCaches();
    resetVirtualMethodCaches();
  }

  public void setDirectMethods(DexEncodedMethod[] methods) {
    assert verifyCorrectnessOfMethodHolders(methods);
    resetDirectMethodCaches();
    backing.setDirectMethods(methods);
  }

  public void setSingleDirectMethod(DexEncodedMethod method) {
    setDirectMethods(new DexEncodedMethod[] {method});
  }

  public void addVirtualMethods(Collection<DexEncodedMethod> methods) {
    assert verifyCorrectnessOfMethodHolders(methods);
    resetVirtualMethodCaches();
    backing.addVirtualMethods(methods);
  }

  public void clearVirtualMethods() {
    resetVirtualMethodCaches();
    backing.clearVirtualMethods();
  }

  public void setVirtualMethods(DexEncodedMethod[] methods) {
    assert verifyCorrectnessOfMethodHolders(methods);
    resetVirtualMethodCaches();
    backing.setVirtualMethods(methods);
  }

  public void virtualizeMethods(Set<DexEncodedMethod> privateInstanceMethods) {
    resetVirtualMethodCaches();
    backing.virtualizeMethods(privateInstanceMethods);
  }

  public boolean hasAnnotations() {
    return traverse(
            method ->
                method.hasAnyAnnotations()
                    ? TraversalContinuation.doBreak()
                    : TraversalContinuation.doContinue())
        .shouldBreak();
  }

  public void useSortedBacking() {
    assert size() == 0;
    backing = MethodMapBacking.createSorted();
  }

  public boolean verify() {
    forEachMethod(
        method -> {
          assert verifyCorrectnessOfMethodHolder(method);
        });
    assert backing.verify();
    return true;
  }

  private boolean verifyCorrectnessOfMethodHolder(DexEncodedMethod method) {
    assert method.getHolderType() == holder.type
        : "Expected method `"
            + method.getReference().toSourceString()
            + "` to have holder `"
            + holder.type.toSourceString()
            + "`";
    return true;
  }

  private boolean verifyCorrectnessOfMethodHolders(DexEncodedMethod[] methods) {
    if (methods == null) {
      return true;
    }
    return verifyCorrectnessOfMethodHolders(Arrays.asList(methods));
  }

  private boolean verifyCorrectnessOfMethodHolders(Iterable<DexEncodedMethod> methods) {
    for (DexEncodedMethod method : methods) {
      assert verifyCorrectnessOfMethodHolder(method);
    }
    return true;
  }

  public String getBackingDescriptionString() {
    return backing.getDescriptionString();
  }
}
