// 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.ir.analysis.type;

import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.OptionalBool;
import com.android.tools.r8.utils.Pair;
import it.unimi.dsi.fastutil.objects.Reference2BooleanMap;
import it.unimi.dsi.fastutil.objects.Reference2BooleanMap.Entry;
import it.unimi.dsi.fastutil.objects.Reference2BooleanMaps;
import it.unimi.dsi.fastutil.objects.Reference2BooleanOpenHashMap;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.BiPredicate;

public class InterfaceCollection {

  public static boolean isKnownToImplement(
      DexType iface, DexType implementor, InternalOptions options) {
    if (options.canHaveZipFileWithMissingCloseableBug()
        && implementor == options.dexItemFactory().zipFileType
        && iface == options.dexItemFactory().closeableType) {
      return false;
    }
    return true;
  }

  public static class Builder {
    private Reference2BooleanMap<DexType> interfaces = new Reference2BooleanOpenHashMap<>();

    private Builder() {}

    public Builder addInterface(DexType iface, DexClass implementor, InternalOptions options) {
      return addInterface(
          iface,
          !implementor.isLibraryClass()
              || isKnownToImplement(iface, implementor.getType(), options));
    }

    public Builder addInterface(DexType iface, DexType implementor, InternalOptions options) {
      return addInterface(iface, isKnownToImplement(iface, implementor, options));
    }

    public Builder addInterface(DexType type, boolean isKnown) {
      interfaces.compute(
          type,
          (existingType, existingIsKnown) ->
              // If the entry is new 'existingIsKnown == null', so we join with (null or true).
              (existingIsKnown == null || existingIsKnown) && isKnown);
      return this;
    }

    public InterfaceCollection build() {
      if (interfaces.isEmpty()) {
        return InterfaceCollection.empty();
      }
      return new InterfaceCollection(interfaces);
    }
  }

  private static final InterfaceCollection EMPTY =
      new InterfaceCollection(Reference2BooleanMaps.emptyMap());

  public static InterfaceCollection empty() {
    return EMPTY;
  }

  public static InterfaceCollection singleton(DexType type) {
    return new InterfaceCollection(Reference2BooleanMaps.singleton(type, true));
  }

  public static Builder builder() {
    return new Builder();
  }

  /**
   * Set of interfaces mapping to an optional presence.
   *
   * <ul>
   *   <li>An unmapped type is known to not be present.
   *   <li>A type mapped to true is known to always be present.
   *   <li>A type mapped to false is not always known to be present.
   */
  private final Reference2BooleanMap<DexType> interfaces;

  private InterfaceCollection(Reference2BooleanMap<DexType> interfaces) {
    assert interfaces != null;
    this.interfaces = interfaces;
  }

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

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

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (!(o instanceof InterfaceCollection)) {
      return false;
    }
    InterfaceCollection that = (InterfaceCollection) o;
    return interfaces.equals(that.interfaces);
  }

  @Override
  public int hashCode() {
    return interfaces.hashCode();
  }

  public void forEach(BiConsumer<DexType, Boolean> fn) {
    interfaces.forEach(fn::accept);
  }

  public boolean anyMatch(BiPredicate<DexType, Boolean> fn) {
    for (Entry<DexType> entry : interfaces.reference2BooleanEntrySet()) {
      if (fn.test(entry.getKey(), entry.getBooleanValue())) {
        return true;
      }
    }
    return false;
  }

  public List<Pair<DexType, Boolean>> getInterfaceList() {
    List<Pair<DexType, Boolean>> list = new ArrayList<>(interfaces.size());
    interfaces.forEach((iface, isKnown) -> list.add(new Pair<>(iface, isKnown)));
    return list;
  }

  public boolean hasSingleKnownInterface() {
    DexType singleKnownInterface = getSingleKnownInterface();
    return singleKnownInterface != null;
  }

  public DexType getSingleKnownInterface() {
    if (interfaces.size() != 1) {
      return null;
    }
    DexType type = interfaces.keySet().iterator().next();
    return interfaces.getBoolean(type) ? type : null;
  }

  public OptionalBool contains(DexType type) {
    Boolean value = interfaces.get(type);
    if (value == null) {
      return OptionalBool.FALSE;
    }
    return value ? OptionalBool.TRUE : OptionalBool.unknown();
  }

  public boolean containsKnownInterface(DexType type) {
    return contains(type).isTrue();
  }
}
