// Copyright (c) 2023, 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.graph;

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

import com.android.tools.r8.utils.ArrayUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.TraversalContinuation;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

public class FieldArrayBacking extends FieldCollectionBacking {

  private DexEncodedField[] staticFields;
  private DexEncodedField[] instanceFields;

  public static FieldCollectionBacking fromArrays(
      DexEncodedField[] staticFields, DexEncodedField[] instanceFields) {
    return new FieldArrayBacking(staticFields, instanceFields);
  }

  private FieldArrayBacking(DexEncodedField[] staticFields, DexEncodedField[] instanceFields) {
    assert staticFields != null;
    assert instanceFields != null;
    this.staticFields = staticFields;
    this.instanceFields = instanceFields;
  }

  @Override
  boolean verify() {
    assert verifyNoDuplicateFields();
    return true;
  }

  private boolean verifyNoDuplicateFields() {
    Set<DexField> unique = Sets.newIdentityHashSet();
    for (DexEncodedField field : fields(alwaysTrue())) {
      boolean changed = unique.add(field.getReference());
      assert changed : "Duplicate field `" + field.getReference().toSourceString() + "`";
    }
    return true;
  }

  @Override
  int numberOfStaticFields() {
    return staticFields.length;
  }

  @Override
  int numberOfInstanceFields() {
    return instanceFields.length;
  }

  @Override
  int size() {
    return staticFields.length + instanceFields.length;
  }

  @Override
  TraversalContinuation<?, ?> traverse(Function<DexEncodedField, TraversalContinuation<?, ?>> fn) {
    for (int i = 0; i < staticFields.length; i++) {
      if (fn.apply(staticFields[i]).shouldBreak()) {
        return TraversalContinuation.doBreak();
      }
    }
    for (int i = 0; i < instanceFields.length; i++) {
      if (fn.apply(instanceFields[i]).shouldBreak()) {
        return TraversalContinuation.doBreak();
      }
    }
    return TraversalContinuation.doContinue();
  }

  @Override
  Iterable<DexEncodedField> fields(Predicate<? super DexEncodedField> predicate) {
    return Iterables.concat(
        Iterables.filter(Arrays.asList(instanceFields), predicate::test),
        Iterables.filter(Arrays.asList(staticFields), predicate::test));
  }

  @Override
  List<DexEncodedField> staticFieldsAsList() {
    if (InternalOptions.assertionsEnabled()) {
      return Collections.unmodifiableList(Arrays.asList(staticFields));
    }
    return Arrays.asList(staticFields);
  }

  @Override
  void appendStaticField(DexEncodedField field) {
    staticFields = appendFieldHelper(staticFields, field);
  }

  @Override
  void appendStaticFields(Collection<DexEncodedField> fields) {
    staticFields = appendFieldsHelper(staticFields, fields);
  }

  @Override
  void clearStaticFields() {
    staticFields = DexEncodedField.EMPTY_ARRAY;
  }

  @Override
  public void setStaticFields(DexEncodedField[] fields) {
    assert fields != null;
    staticFields = fields;
  }

  @Override
  List<DexEncodedField> instanceFieldsAsList() {
    if (InternalOptions.assertionsEnabled()) {
      return Collections.unmodifiableList(Arrays.asList(instanceFields));
    }
    return Arrays.asList(instanceFields);
  }

  @Override
  void appendInstanceField(DexEncodedField field) {
    instanceFields = appendFieldHelper(instanceFields, field);
  }

  @Override
  void appendInstanceFields(Collection<DexEncodedField> fields) {
    instanceFields = appendFieldsHelper(instanceFields, fields);
  }

  @Override
  void clearInstanceFields() {
    instanceFields = DexEncodedField.EMPTY_ARRAY;
  }

  @Override
  void setInstanceFields(DexEncodedField[] fields) {
    assert fields != null;
    instanceFields = fields;
  }

  @Override
  DexEncodedField lookupField(DexField field) {
    DexEncodedField result = lookupInstanceField(field);
    return result == null ? lookupStaticField(field) : result;
  }

  @Override
  DexEncodedField lookupStaticField(DexField field) {
    return lookupFieldHelper(staticFields, field);
  }

  @Override
  DexEncodedField lookupInstanceField(DexField field) {
    return lookupFieldHelper(instanceFields, field);
  }

  @Override
  void replaceFields(Function<DexEncodedField, DexEncodedField> replacement) {
    staticFields =
        replaceFieldsHelper(
            staticFields,
            replacement,
            FieldCollectionBacking::belongsInStaticPool,
            this::appendInstanceFields);
    instanceFields =
        replaceFieldsHelper(
            instanceFields,
            replacement,
            FieldCollectionBacking::belongsInInstancePool,
            this::appendStaticFields);
  }

  private static DexEncodedField[] appendFieldHelper(
      DexEncodedField[] existingItems, DexEncodedField itemToAppend) {
    DexEncodedField[] newFields = new DexEncodedField[existingItems.length + 1];
    System.arraycopy(existingItems, 0, newFields, 0, existingItems.length);
    newFields[existingItems.length] = itemToAppend;
    return newFields;
  }

  private static DexEncodedField[] appendFieldsHelper(
      DexEncodedField[] existingItems, Collection<DexEncodedField> itemsToAppend) {
    DexEncodedField[] newFields = new DexEncodedField[existingItems.length + itemsToAppend.size()];
    System.arraycopy(existingItems, 0, newFields, 0, existingItems.length);
    int i = existingItems.length;
    for (DexEncodedField field : itemsToAppend) {
      newFields[i] = field;
      i++;
    }
    return newFields;
  }

  private static DexEncodedField lookupFieldHelper(DexEncodedField[] items, DexField reference) {
    for (int i = 0; i < items.length; i++) {
      DexEncodedField item = items[i];
      if (reference.match(item)) {
        return item;
      }
    }
    return null;
  }

  private static DexEncodedField[] replaceFieldsHelper(
      DexEncodedField[] fields,
      Function<DexEncodedField, DexEncodedField> replacement,
      Predicate<DexEncodedField> inThisPool,
      Consumer<List<DexEncodedField>> onMovedToOtherPool) {
    List<DexEncodedField> movedToOtherPool = new ArrayList<>();
    for (int i = 0; i < fields.length; i++) {
      DexEncodedField existingField = fields[i];
      assert inThisPool.test(existingField);
      DexEncodedField newField = replacement.apply(existingField);
      assert newField != null;
      if (existingField != newField) {
        if (inThisPool.test(newField)) {
          fields[i] = newField;
        } else {
          fields[i] = null;
          movedToOtherPool.add(newField);
        }
      }
    }
    if (movedToOtherPool.isEmpty()) {
      return fields;
    }
    onMovedToOtherPool.accept(movedToOtherPool);
    return ArrayUtils.filter(
        fields,
        Objects::nonNull,
        DexEncodedField.EMPTY_ARRAY,
        fields.length - movedToOtherPool.size());
  }
}
