/*
 *  // 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;

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.DexEncodedField;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.shaking.KeepClassInfo;
import com.android.tools.r8.utils.IterableUtils;
import com.android.tools.r8.utils.IteratorUtils;
import com.android.tools.r8.utils.collections.BidirectionalManyToOneHashMap;
import com.android.tools.r8.utils.collections.BidirectionalManyToOneMap;
import com.android.tools.r8.utils.collections.MutableBidirectionalManyToOneMap;
import com.google.common.collect.Iterables;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.function.Consumer;
import java.util.function.Predicate;

public class MergeGroup implements Collection<DexProgramClass> {

  public static class Metadata {}

  private final LinkedList<DexProgramClass> classes;

  private DexField classIdField;
  private DexProgramClass target = null;
  private Metadata metadata = null;

  private BidirectionalManyToOneMap<DexEncodedField, DexEncodedField> instanceFieldMap;

  public MergeGroup() {
    this.classes = new LinkedList<>();
  }

  public MergeGroup(DexProgramClass clazz) {
    this();
    add(clazz);
  }

  public MergeGroup(Iterable<DexProgramClass> classes) {
    this();
    Iterables.addAll(this.classes, classes);
  }

  public void applyMetadataFrom(MergeGroup group) {
    if (metadata == null) {
      metadata = group.metadata;
    }
  }

  @Override
  public boolean add(DexProgramClass clazz) {
    return classes.add(clazz);
  }

  public boolean add(MergeGroup group) {
    return classes.addAll(group.getClasses());
  }

  @Override
  public boolean addAll(Collection<? extends DexProgramClass> classes) {
    return this.classes.addAll(classes);
  }

  @Override
  public void clear() {
    classes.clear();
  }

  @Override
  public boolean contains(Object o) {
    return classes.contains(o);
  }

  @Override
  public boolean containsAll(Collection<?> collection) {
    return classes.containsAll(collection);
  }

  public void forEachSource(Consumer<DexProgramClass> consumer) {
    assert hasTarget();
    for (DexProgramClass clazz : classes) {
      if (clazz != target) {
        consumer.accept(clazz);
      }
    }
  }

  public LinkedList<DexProgramClass> getClasses() {
    return classes;
  }

  public boolean hasClassIdField() {
    return classIdField != null;
  }

  public DexField getClassIdField() {
    assert hasClassIdField();
    return classIdField;
  }

  public void setClassIdField(DexField classIdField) {
    this.classIdField = classIdField;
  }

  public boolean hasInstanceFieldMap() {
    return instanceFieldMap != null;
  }

  public BidirectionalManyToOneMap<DexEncodedField, DexEncodedField> getInstanceFieldMap() {
    assert hasInstanceFieldMap();
    return instanceFieldMap;
  }

  public void selectInstanceFieldMap(AppView<? extends AppInfoWithClassHierarchy> appView) {
    assert hasTarget();
    MutableBidirectionalManyToOneMap<DexEncodedField, DexEncodedField> instanceFieldMap =
        BidirectionalManyToOneHashMap.newLinkedHashMap();
    forEachSource(
        source ->
            ClassInstanceFieldsMerger.mapFields(appView, source, target, instanceFieldMap::put));
    setInstanceFieldMap(instanceFieldMap);
  }

  public void setInstanceFieldMap(
      BidirectionalManyToOneMap<DexEncodedField, DexEncodedField> instanceFieldMap) {
    assert !hasInstanceFieldMap();
    this.instanceFieldMap = instanceFieldMap;
  }

  public Iterable<DexProgramClass> getSources() {
    assert hasTarget();
    return Iterables.filter(classes, clazz -> clazz != target);
  }

  public DexType getSuperType() {
    assert IterableUtils.allIdentical(classes, DexClass::getSuperType);
    return getClasses().getFirst().getSuperType();
  }

  public boolean hasTarget() {
    return target != null;
  }

  public DexProgramClass getTarget() {
    return target;
  }

  public ProgramField getTargetInstanceField(ProgramField field) {
    assert hasTarget();
    assert hasInstanceFieldMap();
    if (field.getHolder() == getTarget()) {
      return field;
    }
    DexEncodedField targetField = getInstanceFieldMap().get(field.getDefinition());
    return new ProgramField(getTarget(), targetField);
  }

  public void selectTarget(AppView<? extends AppInfoWithClassHierarchy> appView) {
    Iterable<DexProgramClass> candidates = Iterables.filter(getClasses(), DexClass::isPublic);
    if (IterableUtils.isEmpty(candidates)) {
      candidates = getClasses();
    }
    Iterator<DexProgramClass> candidateIterator = candidates.iterator();
    DexProgramClass target = IterableUtils.first(candidates);
    while (candidateIterator.hasNext()) {
      DexProgramClass current = candidateIterator.next();
      KeepClassInfo keepClassInfo = appView.getKeepInfo().getClassInfo(current);
      if (keepClassInfo.isMinificationAllowed(appView.options())) {
        target = current;
        break;
      }
      // Select the target with the shortest name.
      if (current.getType().getDescriptor().size() < target.getType().getDescriptor().size) {
        target = current;
      }
    }
    setTarget(appView.testing().horizontalClassMergingTarget.apply(appView, candidates, target));
  }

  private void setTarget(DexProgramClass target) {
    assert !hasTarget();
    this.target = target;
  }

  public boolean isTrivial() {
    return size() < 2;
  }

  public boolean isNonTrivial() {
    return !isTrivial();
  }

  @Override
  public boolean isEmpty() {
    return classes.isEmpty();
  }

  public boolean isClassGroup() {
    return !isInterfaceGroup();
  }

  public boolean isInterfaceGroup() {
    assert !isEmpty();
    assert IterableUtils.allIdentical(getClasses(), DexClass::isInterface);
    return getClasses().getFirst().isInterface();
  }

  @Override
  public Iterator<DexProgramClass> iterator() {
    return classes.iterator();
  }

  @Override
  public int size() {
    return classes.size();
  }

  @Override
  public boolean remove(Object o) {
    return classes.remove(o);
  }

  @Override
  public boolean removeAll(Collection<?> collection) {
    return classes.removeAll(collection);
  }

  public DexProgramClass removeFirst(Predicate<DexProgramClass> predicate) {
    return IteratorUtils.removeFirst(iterator(), predicate);
  }

  @Override
  public boolean removeIf(Predicate<? super DexProgramClass> predicate) {
    return classes.removeIf(predicate);
  }

  public DexProgramClass removeLast() {
    return classes.removeLast();
  }

  @Override
  public boolean retainAll(Collection<?> collection) {
    return collection.retainAll(collection);
  }

  @Override
  public Object[] toArray() {
    return classes.toArray();
  }

  @Override
  public <T> T[] toArray(T[] ts) {
    return classes.toArray(ts);
  }
}
