// Copyright (c) 2017, 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.errors.CompilationError;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.type.InterfaceCollection.Builder;
import com.android.tools.r8.utils.BooleanBox;
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.OptionalBool;
import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.SetUtils;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Queue;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

public class ClassTypeElement extends ReferenceTypeElement {

  // Least upper bound of interfaces that this class type is implementing.
  // Lazily computed on demand via DexItemFactory, where the canonicalized set will be maintained.
  private InterfaceCollection lazyInterfaces;
  private AppView<? extends AppInfoWithClassHierarchy> appView;
  // On-demand link between other nullability-variants.
  private final NullabilityVariants<ClassTypeElement> variants;
  private final DexType type;

  public static ClassTypeElement create(
      DexType classType,
      Nullability nullability,
      AppView<? extends AppInfoWithClassHierarchy> appView,
      InterfaceCollection interfaces) {
    assert appView != null;
    assert appView.enableWholeProgramOptimizations();
    assert interfaces != null;
    return NullabilityVariants.create(
        nullability,
        variants -> new ClassTypeElement(classType, nullability, interfaces, variants, appView));
  }

  public static ClassTypeElement create(
      DexType classType,
      Nullability nullability,
      AppView<? extends AppInfoWithClassHierarchy> appView) {
    assert appView != null;
    assert appView.enableWholeProgramOptimizations();
    return NullabilityVariants.create(
        nullability,
        variants -> new ClassTypeElement(classType, nullability, null, variants, appView));
  }

  public static ClassTypeElement createForD8(DexType classType, Nullability nullability) {
    return NullabilityVariants.create(
        nullability,
        variants ->
            new ClassTypeElement(
                classType, nullability, InterfaceCollection.empty(), variants, null));
  }

  private ClassTypeElement(
      DexType classType,
      Nullability nullability,
      InterfaceCollection interfaces,
      NullabilityVariants<ClassTypeElement> variants,
      AppView<? extends AppInfoWithClassHierarchy> appView) {
    super(nullability);
    assert appView != null
        ? appView.enableWholeProgramOptimizations()
        : (interfaces != null && interfaces.isEmpty());
    assert classType.isClassType();
    this.type = classType;
    this.appView = appView;
    this.lazyInterfaces = interfaces;
    this.variants = variants;
  }

  public DexType getClassType() {
    return type;
  }

  public InterfaceCollection getInterfaces() {
    if (lazyInterfaces == null) {
      // Class type interfaces are cached on DexItemFactory.
      assert appView != null;
      assert appView.enableWholeProgramOptimizations();
      return appView
          .dexItemFactory()
          .getOrComputeLeastUpperBoundOfImplementedInterfaces(type, appView);
    }
    return lazyInterfaces;
  }

  private ClassTypeElement createVariant(
      Nullability nullability, NullabilityVariants<ClassTypeElement> variants) {
    assert this.nullability != nullability;
    return new ClassTypeElement(type, nullability, lazyInterfaces, variants, appView);
  }

  @Override
  public ClassTypeElement getOrCreateVariant(Nullability nullability) {
    ClassTypeElement variant = variants.get(nullability);
    if (variant != null) {
      return variant;
    }
    return variants.getOrCreateElement(nullability, this::createVariant);
  }

  @Override
  public boolean isBasedOnMissingClass(AppView<? extends AppInfoWithClassHierarchy> appView) {
    return appView.appInfo().isMissingOrHasMissingSuperType(getClassType())
        || getInterfaces()
            .anyMatch((iface, isKnown) -> appView.appInfo().isMissingOrHasMissingSuperType(iface));
  }

  @Override
  public boolean isClassType() {
    return true;
  }

  @Override
  public ClassTypeElement asClassType() {
    return this;
  }

  @Override
  public ClassTypeElement asDefinitelyNotNull() {
    return getOrCreateVariant(Nullability.definitelyNotNull());
  }

  @Override
  public ClassTypeElement asMeetWithNotNull() {
    return getOrCreateVariant(nullability.meet(Nullability.definitelyNotNull()));
  }

  @Override
  public ClassTypeElement joinNullability(Nullability nullability) {
    return getOrCreateVariant(nullability().join(nullability));
  }

  @Override
  public ClassTypeElement meetNullability(Nullability nullability) {
    return getOrCreateVariant(nullability().meet(nullability));
  }

  @Override
  public String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append(nullability);
    builder.append(" ");
    builder.append(type);
    builder.append(" {");
    InterfaceCollection interfaces = getInterfaces();
    List<Pair<DexType, Boolean>> sortedInterfaces = interfaces.getInterfaceList();
    sortedInterfaces.sort(Comparator.comparing(Pair::getFirst));
    builder.append(
        sortedInterfaces.stream()
            .map(
                pair ->
                    pair.getSecond()
                        ? pair.getFirst().toString()
                        : ("maybe(" + pair.getFirst() + ")"))
            .collect(Collectors.joining(", ")));
    builder.append("}");
    return builder.toString();
  }

  @Override
  public int hashCode() {
    // The interfaces of a type do not contribute to its hashCode as they are lazily computed.
    return Objects.hash(nullability, type);
  }

  @Override
  public TypeElement fixupClassTypeReferences(
      AppView<? extends AppInfoWithClassHierarchy> ignore,
      Function<DexType, DexType> mapping,
      Set<DexType> prunedTypes) {
    assert appView != null;
    assert appView.enableWholeProgramOptimizations();

    DexType mappedType = mapping.apply(type);
    if (mappedType.isPrimitiveType()) {
      return PrimitiveTypeElement.fromDexType(mappedType, false);
    }

    // If there are no interfaces, then just return the mapped type element. Otherwise, the list of
    // interfaces require rewriting.
    if (lazyInterfaces == null || lazyInterfaces.isEmpty()) {
      return mappedType == type ? this : create(mappedType, nullability, appView);
    }

    // For most types there will not have been a change thus we iterate without allocating a new
    // set for holding modified interfaces.
    BooleanBox hasChangedInterfaces = new BooleanBox();
    Box<DexClass> interfaceToClassChange = new Box<>();
    getInterfaces()
        .forEach(
            (iface, isKnown) -> {
              if (prunedTypes.contains(iface)) {
                return;
              }
              DexType substitutedType = mapping.apply(iface);
              if (iface != substitutedType) {
                hasChangedInterfaces.set();
                DexClass mappedClass = appView.definitionFor(substitutedType);
                if (!mappedClass.isInterface()) {
                  if (interfaceToClassChange.isSet()
                      && mappedClass != interfaceToClassChange.get()) {
                    throw new CompilationError(
                        "More than one interface has changed to a class: "
                            + interfaceToClassChange.get()
                            + " and "
                            + mappedClass);
                  }
                  interfaceToClassChange.set(mappedClass);
                }
              }
            });
    if (hasChangedInterfaces.get()) {
      if (interfaceToClassChange.isSet()) {
        assert !interfaceToClassChange.get().isInterface();
        assert mappedType == appView.dexItemFactory().objectType;
        return create(interfaceToClassChange.get().type, nullability, appView);
      } else {
        Builder builder = InterfaceCollection.builder();
        lazyInterfaces.forEach(
            (iface, isKnown) -> {
              DexType rewritten = mapping.apply(iface);
              assert iface == rewritten || isKnown : "Rewritten implies program types thus known.";
              builder.addInterface(rewritten, isKnown);
            });
        return create(mappedType, nullability, appView, builder.build());
      }
    }
    return mappedType == type ? this : create(mappedType, nullability, appView, getInterfaces());
  }

  ClassTypeElement join(ClassTypeElement other, AppView<?> appView) {
    if (!appView.enableWholeProgramOptimizations()) {
      assert lazyInterfaces != null;
      assert lazyInterfaces.isEmpty();
      assert other.lazyInterfaces != null;
      assert other.lazyInterfaces.isEmpty();
      return ClassTypeElement.createForD8(
          getClassType() == other.getClassType()
              ? getClassType()
              : appView.dexItemFactory().objectType,
          nullability().join(other.nullability()));
    }
    return joinWithClassHierarchy(other);
  }

  private ClassTypeElement joinWithClassHierarchy(ClassTypeElement other) {
    assert appView != null;
    assert appView.enableWholeProgramOptimizations();
    DexType lubType =
        computeLeastUpperBoundOfClasses(appView.appInfo(), getClassType(), other.getClassType());
    InterfaceCollection c1lubItfs = getInterfaces();
    InterfaceCollection c2lubItfs = other.getInterfaces();
    InterfaceCollection lubItfs =
        c1lubItfs.equals(c2lubItfs)
            ? c1lubItfs
            : computeLeastUpperBoundOfInterfaces(appView, c1lubItfs, c2lubItfs);
    InterfaceCollection lubItfsDefault =
        appView
            .dexItemFactory()
            .getOrComputeLeastUpperBoundOfImplementedInterfaces(lubType, appView);
    Nullability lubNullability = nullability().join(other.nullability());

    // If the computed interfaces are identical to the interfaces of `lubType`, then do not include
    // the interfaces in the ClassTypeElement. This canonicalization of interfaces reduces memory,
    // but also reduces the amount of work involved in lens rewriting class type elements (the null
    // element does not require any rewriting).
    //
    // From a correctness point of view, both solutions should work.
    return lubItfs.equals(lubItfsDefault)
        ? create(lubType, lubNullability, appView)
        : create(lubType, lubNullability, appView, lubItfs);
  }

  /**
   * Internal marker for finding the LUB between sets of interfaces.
   *
   * <p>The marker is used both as the identification of which side the traversal is on and if that
   * item is known to always be present. That use denotes a immutable use fo the marker and reuses
   * the static constants defined below. When traversing the interface super chains each point is
   * mapped to a mutable marking that keeps track of what paths have reached it. The mutable use is
   * allocated with 'createEmpty' and updated with 'merge'.
   */
  private static class InterfaceMarker {

    // Each side is tracked with a three-valued marking.
    // Note that the value FALSE is not part of the possible three values, only:
    //   FALSE: not marked / not present.
    //   TRUE: marked and known to be present.
    //   UNKNOWN: marked and unknown if actually present.
    private OptionalBool left;
    private OptionalBool right;

    static final InterfaceMarker LEFT_KNOWN =
        new InterfaceMarker(OptionalBool.TRUE, OptionalBool.FALSE);
    static final InterfaceMarker LEFT_UNKNOWN =
        new InterfaceMarker(OptionalBool.UNKNOWN, OptionalBool.FALSE);
    static final InterfaceMarker RIGHT_KNOWN =
        new InterfaceMarker(OptionalBool.FALSE, OptionalBool.TRUE);
    static final InterfaceMarker RIGHT_UNKNOWN =
        new InterfaceMarker(OptionalBool.FALSE, OptionalBool.UNKNOWN);

    static InterfaceMarker forLeft(boolean isKnown) {
      return isKnown ? LEFT_KNOWN : LEFT_UNKNOWN;
    }

    static InterfaceMarker forRight(boolean isKnown) {
      return isKnown ? RIGHT_KNOWN : RIGHT_UNKNOWN;
    }

    static InterfaceMarker createUnmarked() {
      return new InterfaceMarker(OptionalBool.FALSE, OptionalBool.FALSE);
    }

    public InterfaceMarker(OptionalBool left, OptionalBool right) {
      this.left = left;
      this.right = right;
      assert !isMarkedOnBothSides();
    }

    boolean isMarked() {
      return left.isPossiblyTrue() || right.isPossiblyTrue();
    }

    boolean isMarkedOnBothSides() {
      return left.isPossiblyTrue() && right.isPossiblyTrue();
    }

    static OptionalBool knownIfAnyIsKnown(OptionalBool v1, OptionalBool v2) {
      assert v1.isPossiblyTrue() || v2.isPossiblyTrue();
      return v1.isTrue() || v2.isTrue() ? OptionalBool.TRUE : OptionalBool.UNKNOWN;
    }

    boolean knownIfBothAreKnown() {
      assert isMarkedOnBothSides();
      return left.isTrue() && right.isTrue();
    }

    boolean merge(InterfaceMarker marker) {
      assert marker.isMarked();
      assert !marker.isMarkedOnBothSides();
      if (marker.left.isPossiblyTrue()) {
        OptionalBool oldLeft = left;
        left = knownIfAnyIsKnown(left, marker.left);
        // Only continue if the other side is absent and this side changed.
        return right.isFalse() && left != oldLeft;
      } else {
        OptionalBool oldRight = right;
        right = knownIfAnyIsKnown(right, marker.right);
        // Only continue if the other side is absent and this side changed.
        return left.isFalse() && right != oldRight;
      }
    }
  }

  private static class InterfaceWithMarker {
    final DexType itf;
    final InterfaceMarker marker;

    InterfaceWithMarker(DexType itf, InterfaceMarker marker) {
      this.itf = itf;
      this.marker = marker;
    }
  }

  public static DexType computeLeastUpperBoundOfClasses(
      AppInfoWithClassHierarchy appInfo, DexType type1, DexType type2) {
    // Compiling R8 with R8, this hits more than 1/3 of cases.
    if (type1 == type2) {
      return type1;
    }
    // Compiling R8 with R8, this hits more than 1/3 of cases.
    DexType objectType = appInfo.dexItemFactory().objectType;
    if (type1 == objectType || type2 == objectType) {
      return objectType;
    }
    // Compiling R8 with R8, there are no hierarchies above height 10.
    // The overhead of a hash map likely outweighs the speed of scanning an array.
    Collection<DexType> types = new ArrayList<>(10);
    DexType type = type1;
    while (true) {
      if (type == type2) {
        return type;
      }
      types.add(type);
      DexClass clazz = appInfo.definitionFor(type);
      if (clazz == null || clazz.superType == null || clazz.superType == objectType) {
        break;
      }
      type = clazz.superType;
    }
    // In pathological cases, realloc to a set if large.
    if (types.size() > 20) {
      types = SetUtils.newIdentityHashSet(types);
    }
    type = type2;
    while (true) {
      if (types.contains(type)) {
        return type;
      }
      DexClass clazz = appInfo.definitionFor(type);
      if (clazz == null || clazz.superType == null || clazz.superType == objectType) {
        break;
      }
      type = clazz.superType;
    }
    return objectType;
  }

  public static InterfaceCollection computeLeastUpperBoundOfInterfaces(
      AppView<? extends AppInfoWithClassHierarchy> appView,
      InterfaceCollection s1,
      InterfaceCollection s2) {
    if (s1.isEmpty() || s2.isEmpty()) {
      return InterfaceCollection.empty();
    }
    InterfaceCollection cached =
        appView.dexItemFactory().leastUpperBoundOfInterfacesTable.get(s1, s2);
    if (cached != null) {
      return cached;
    }
    cached = appView.dexItemFactory().leastUpperBoundOfInterfacesTable.get(s2, s1);
    if (cached != null) {
      return cached;
    }
    Map<DexType, InterfaceMarker> seen = new IdentityHashMap<>();
    Queue<InterfaceWithMarker> worklist = new ArrayDeque<>();
    s1.forEach(
        (itf1, isKnown) ->
            worklist.add(new InterfaceWithMarker(itf1, InterfaceMarker.forLeft(isKnown))));
    s2.forEach(
        (itf2, isKnown) ->
            worklist.add(new InterfaceWithMarker(itf2, InterfaceMarker.forRight(isKnown))));

    while (!worklist.isEmpty()) {
      InterfaceWithMarker item = worklist.poll();
      DexType itf = item.itf;
      InterfaceMarker marker = item.marker;
      InterfaceMarker marking = seen.computeIfAbsent(itf, k -> InterfaceMarker.createUnmarked());
      if (marking.merge(marker)) {
        // Put super interfaces into the worklist.
        DexClass itfClass = appView.definitionFor(itf);
        if (itfClass != null) {
          for (DexType superItf : itfClass.interfaces.values) {
            worklist.add(new InterfaceWithMarker(superItf, marker));
          }
        }
      }
    }

    List<Pair<DexType, Boolean>> commonlyVisited = new ArrayList<>(seen.size());
    seen.forEach(
        (itf, marking) -> {
          // Keep commonly visited interfaces only
          if (marking.isMarkedOnBothSides()) {
            commonlyVisited.add(new Pair<>(itf, marking.knownIfBothAreKnown()));
          }
        });

    Builder lubBuilder = InterfaceCollection.builder();
    for (Pair<DexType, Boolean> entry : commonlyVisited) {
      // If there is a strict sub interface of this interface, it is not the least element.
      boolean notTheLeast = false;
      for (Pair<DexType, Boolean> other : commonlyVisited) {
        if (appView.appInfo().isStrictSubtypeOf(other.getFirst(), entry.getFirst())) {
          notTheLeast = true;
          break;
        }
      }
      if (notTheLeast) {
        continue;
      }
      lubBuilder.addInterface(entry.getFirst(), entry.getSecond());
    }
    InterfaceCollection lub = lubBuilder.build();
    // Cache the computation result only if the given two sets of interfaces are different.
    if (!s1.equals(s2)) {
      synchronized (appView.dexItemFactory().leastUpperBoundOfInterfacesTable) {
        appView.dexItemFactory().leastUpperBoundOfInterfacesTable.put(s1, s2, lub);
      }
    }
    return lub;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (!(o instanceof ClassTypeElement)) {
      return false;
    }
    ClassTypeElement other = (ClassTypeElement) o;
    if (nullability() != other.nullability()) {
      return false;
    }
    if (!type.equals(other.type)) {
      return false;
    }
    return getInterfaces().equals(other.getInterfaces());
  }
}
