package com.kickstarter.libs.utils;

import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.util.Pair;

import com.kickstarter.libs.preferences.BooleanPreference;

import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;

import auto.parcel.AutoParcel;
import rx.functions.Func2;

public final class DiffUtils {
  private DiffUtils() {}

  @AutoParcel
  public static abstract class Diff implements Parcelable {
    public abstract @NonNull List<Integer> insertions();
    public abstract @NonNull List<Integer> deletions();
    public abstract @NonNull List<Integer> updates();

    @AutoParcel.Builder
    public abstract static class Builder {
      public abstract Builder insertions(List<Integer> __);
      public abstract Builder deletions(List<Integer> __);
      public abstract Builder updates(List<Integer> __);
      public abstract Diff build();
    }

    public static Builder builder() {
      return new AutoParcel_DiffUtils_Diff.Builder()
        .insertions(new ArrayList<>())
        .deletions(new ArrayList<>())
        .updates(new ArrayList<>());
    }

    public abstract Builder toBuilder();
  }

  public static @NonNull <T> Diff diff(final @NonNull List<T> oldItems, final @NonNull List<T> newItems) {
    return DiffUtils.diff(oldItems, newItems, Object::equals);
  }

  public static @NonNull <T> Diff diff(final @NonNull List<T> oldItems, final @NonNull List<T> newItems, Func2<T, T, Boolean> matches) {
    final List<Integer> insertions = new ArrayList<>();
    final List<Integer> deletions = new ArrayList<>();
    final List<Integer> updates = new ArrayList<>();

    final List<T> missingItems = ListUtils.difference(oldItems, newItems, matches);
    for (final T item : missingItems) {
      deletions.add(oldItems.indexOf(item));
    }

    final List<T> addedItems = ListUtils.difference(newItems, oldItems, matches);
    for (final T item : addedItems) {
      insertions.add(newItems.indexOf(item));
    }

    final List<T> maybeUpdatedItems = ListUtils.intersection(oldItems, newItems, matches);
    for (final T maybeUpdatedItem : maybeUpdatedItems) {
      final T oldItem = ListUtils.find(oldItems, maybeUpdatedItem, matches);
      final T newItem = ListUtils.find(newItems, maybeUpdatedItem, matches);

      if (!oldItem.equals(newItem)) {
        updates.add(ListUtils.indexOf(oldItems, oldItem));
      }
    }

    return Diff.builder()
      .insertions(insertions)
      .deletions(deletions)
      .updates(updates)
      .build();
  }
}

@@ -425,23 +425,16 @@
  public 
-static 
 abstract
@@ -434,16 +434,23 @@
 bstract 
+static 
 class Di
@@ -1467,16 +1467,35 @@
 ewItems,
+%0A    final @NonNull
  Func2%3CT
@@ -1515,24 +1515,25 @@
  matches) %7B%0A
+%0A
     final Li

Fix order of modifier, make func final/nonnull