// 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.utils.structural;

import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.utils.structural.StructuralItem.CompareToAccept;
import com.android.tools.r8.utils.structural.StructuralItem.HashingAccept;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.ToDoubleFunction;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;

public abstract class StructuralSpecification<T, V extends StructuralSpecification<T, V>> {

  abstract V self();

  /** Apply a structural mapping to the present specification. */
  public final V withSpec(StructuralMapping<T> spec) {
    spec.apply(this);
    return self();
  }

  /**
   * Base for accessing and visiting a sub-part on an item.
   *
   * <p>This specifies the getter for the sub-part as well as all of the methods that are required
   * for visiting. The required methods coincide with the requirements of StructuralItem.
   *
   * <p>It is preferable to use withItem and make the item itself implement StructuralItem.
   */
  @Deprecated
  public final <S> V withCustomItem(
      Function<T, S> getter, CompareToAccept<S> compare, HashingAccept<S> hasher) {
    return withConditionalCustomItem(t -> true, getter, compare, hasher);
  }

  public final <S> V withCustomItem(Function<T, S> getter, StructuralAcceptor<S> acceptor) {
    return withCustomItem(getter, acceptor, acceptor);
  }

  /** Base implementation for visiting an item. */
  protected abstract <S> V withConditionalCustomItem(
      Predicate<T> predicate,
      Function<T, S> getter,
      CompareToAccept<S> compare,
      HashingAccept<S> hasher);

  /** Base implementation for visiting an enumeration of items. */
  protected abstract <S> V withCustomItemIterator(
      Function<T, Iterator<S>> getter, CompareToAccept<S> compare, HashingAccept<S> hasher);

  public final <S> V withCustomItemCollection(
      Function<T, Collection<S>> getter, StructuralAcceptor<S> acceptor) {
    return withCustomItemIterator(getter.andThen(Collection::iterator), acceptor, acceptor);
  }

  /**
   * Specification for a "specified" item.
   *
   * <p>Using this the visiting methods are could based on the implementation of the Specified
   * interface.
   */
  public final <S extends StructuralItem<S>> V withItem(Function<T, S> getter) {
    return withConditionalItem(t -> true, getter);
  }

  public final <S extends StructuralItem<S>> V withNullableItem(Function<T, S> getter) {
    return withConditionalItem(s -> getter.apply(s) != null, getter);
  }

  public final <S extends StructuralItem<S>> V withConditionalItem(
      Predicate<T> predicate, Function<T, S> getter) {
    return withConditionalCustomItem(
        predicate, getter, StructuralItem::acceptCompareTo, StructuralItem::acceptHashing);
  }

  public final <S extends StructuralItem<S>> V withItemIterator(Function<T, Iterator<S>> getter) {
    return withCustomItemIterator(
        getter, StructuralItem::acceptCompareTo, StructuralItem::acceptHashing);
  }

  public final <S extends StructuralItem<S>> V withItemCollection(
      Function<T, Collection<S>> getter) {
    return withItemIterator(getter.andThen(Collection::iterator));
  }

  public final <S extends StructuralItem<S>> V withItemArray(Function<T, S[]> getter) {
    return withItemIterator(getter.andThen(a -> Arrays.asList(a).iterator()));
  }

  public final <S extends StructuralItem<S>> V withItemArrayAllowingNullMembers(
      Function<T, S[]> getter) {
    return withCustomItemIterator(
        getter.andThen(a -> Arrays.asList(a).iterator()),
        (a, b, visitor) -> {
          if (a == null || b == null) {
            return visitor.visitBool(a != null, b != null);
          }
          return a.acceptCompareTo(b, visitor);
        },
        (a, visitor) -> {
          if (a == null) {
            visitor.visitInt(0);
          } else {
            a.acceptHashing(visitor);
          }
        });
  }

  /**
   * Helper to declare an assert on the item.
   *
   * <p>Only run if running with -ea. Must be run on any item being visited (ie, both in the case of
   * comparisons and equality).
   */
  public abstract V withAssert(Predicate<T> predicate);

  // Primitive Java types. These will need overriding to avoid boxing.
  public abstract V withBool(Predicate<T> getter);

  public abstract V withInt(ToIntFunction<T> getter);

  public abstract V withLong(ToLongFunction<T> getter);

  public abstract V withDouble(ToDoubleFunction<T> getter);

  public abstract V withIntArray(Function<T, int[]> getter);

  public abstract V withShortArray(Function<T, short[]> getter);

  public abstract V withDexReference(Function<T, DexReference> getter);
}
