// Copyright (c) 2020, 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.horizontalclassmerging.policies;

import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethodSignature;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.horizontalclassmerging.HorizontalClassMerger.Mode;
import com.android.tools.r8.horizontalclassmerging.MergeGroup;
import com.android.tools.r8.horizontalclassmerging.MultiClassPolicy;
import com.android.tools.r8.utils.WorkList;
import com.android.tools.r8.utils.collections.DexMethodSignatureMap;
import com.android.tools.r8.utils.collections.DexMethodSignatureSet;
import com.google.common.collect.Lists;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Function;

/**
 * For interfaces, we cannot introduce an instance field `int $r8$classId`. Therefore, we can't
 * merge two interfaces that declare the same default interface method.
 *
 * <p>This policy attempts to split a merge group consisting of interfaces into smaller merge groups
 * such that each pairs of interfaces in each merge group does not have conflicting default
 * interface methods.
 */
public class NoDefaultInterfaceMethodMerging extends MultiClassPolicy {

  private final AppView<?> appView;
  private final DexType MULTIPLE_SENTINEL;

  public NoDefaultInterfaceMethodMerging(AppView<?> appView, Mode mode) {
    this.appView = appView;
    // Use the java.lang.Object type to indicate more than one interface type, as that type
    // itself is not an interface type.
    this.MULTIPLE_SENTINEL = appView.dexItemFactory().objectType;
  }

  @Override
  public Collection<MergeGroup> apply(MergeGroup group) {
    // Split the group into smaller groups such that no default methods collide.
    // TODO(b/229951607): This fixes the ICCE issue for synthetic lambda classes, but a more
    //  general solution possibly extending the policy NoDefaultInterfaceMethodCollisions.
    Map<MergeGroup, DexMethodSignatureMap<DexType>> newGroups = new LinkedHashMap<>();
    for (DexProgramClass clazz : group) {
      addClassToGroup(
          clazz,
          newGroups,
          group.isInterfaceGroup()
              ? this::collectDefaultMethodsInInterfaces
              : this::collectDefaultMethodsInImplementedInterfaces);
    }

    return removeTrivialGroups(Lists.newLinkedList(newGroups.keySet()));
  }

  private void addClassToGroup(
      DexProgramClass clazz,
      Map<MergeGroup, DexMethodSignatureMap<DexType>> newGroups,
      Function<DexProgramClass, DexMethodSignatureMap<DexType>> fn) {
    DexMethodSignatureMap<DexType> classSignatures = fn.apply(clazz);

    // Find a group that does not have any collisions with `clazz`.
    nextGroup:
    for (Entry<MergeGroup, DexMethodSignatureMap<DexType>> entry : newGroups.entrySet()) {
      MergeGroup group = entry.getKey();
      DexMethodSignatureMap<DexType> groupSignatures = entry.getValue();
      if (!groupSignatures.containsAnyKeyOf(classSignatures.keySet())) {
        groupSignatures.putAll(classSignatures);
        group.add(clazz);
        return;
      } else {
        DexMethodSignatureSet overlappingSignatures =
            groupSignatures.intersectionWithKeys(classSignatures.keySet());
        for (DexMethodSignature signature : overlappingSignatures) {
          if ((groupSignatures.get(signature) != classSignatures.get(signature))
              || (groupSignatures.get(signature) == MULTIPLE_SENTINEL)) {
            continue nextGroup;
          }
          groupSignatures.putAll(classSignatures);
          group.add(clazz);
          return;
        }
      }
    }

    // Else create a new group.
    newGroups.put(new MergeGroup(clazz), classSignatures);
  }

  private void addDefaultMethods(DexMethodSignatureMap<DexType> signatures, DexProgramClass iface) {
    // When the same signature is added from several interfaces just move to the "multiple" state
    // and do not keep track of the actual interfaces.
    iface.forEachProgramVirtualMethodMatching(
        DexEncodedMethod::isDefaultMethod,
        method ->
            signatures.merge(
                method.getDefinition(),
                iface.getType(),
                (ignoreKey, current) -> current == iface.getType() ? current : MULTIPLE_SENTINEL));
  }

  private DexMethodSignatureMap<DexType> collectDefaultMethodsInInterfaces(DexProgramClass iface) {
    assert iface.isInterface();
    DexMethodSignatureMap<DexType> signatures = DexMethodSignatureMap.create();
    WorkList<DexProgramClass> workList = WorkList.newIdentityWorkList();
    workList.addIfNotSeen(iface);
    while (workList.hasNext()) {
      DexProgramClass item = workList.next();
      assert item.isInterface();
      addDefaultMethods(signatures, item);
      addInterfacesToWorklist(item, workList);
    }
    return signatures;
  }

  // TODO(b/229951607): This only adresses the ICCE issue for synthetic lambda classes.
  private DexMethodSignatureMap<DexType> collectDefaultMethodsInImplementedInterfaces(
      DexProgramClass clazz) {
    assert !clazz.isInterface();
    DexMethodSignatureMap<DexType> signatures = DexMethodSignatureMap.create();
    WorkList<DexProgramClass> workList = WorkList.newIdentityWorkList();
    addInterfacesToWorklist(clazz, workList);
    while (workList.hasNext()) {
      DexProgramClass item = workList.next();
      assert item.isInterface();
      addDefaultMethods(signatures, item);
      addInterfacesToWorklist(item, workList);
    }
    return signatures;
  }

  private void addInterfacesToWorklist(DexProgramClass clazz, WorkList<DexProgramClass> worklist) {
    for (DexType iface : clazz.getInterfaces()) {
      DexProgramClass ifaceDefinition = appView.programDefinitionFor(iface, clazz);
      if (ifaceDefinition != null && ifaceDefinition.isInterface()) {
        worklist.addIfNotSeen(ifaceDefinition);
      }
    }
  }

  @Override
  public String getName() {
    return "NoDefaultInterfaceMethodMerging";
  }
}
