package com.kickstarter.libs.utils;

import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import java.util.ArrayList;
import java.util.List;

public class ListUtils {
  private ListUtils() {
    throw new AssertionError();
  }

  /**
   * Returns an empty list.
   */
  @NonNull public static <T> List<T> empty() {
    return new ArrayList<>();
  }

  /**
   * Concats the second argument onto the end of the first, but also mutates the
   * first argument.
   */
  public static <T> List<T> mutatingConcat(@NonNull final List<T> xs, @NonNull final List<T> ys) {
    xs.addAll(ys);
    return xs;
  }

  /**
   * Concats the second argument onto the end of the first without mutating
   * either list.
   */
  public static <T> List<T> concat(@NonNull final List<T> xs, @NonNull final List<T> ys) {
    final List<T> zs = new ArrayList<>(xs);
    ListUtils.mutatingConcat(zs, ys);
    return zs;
  }

  /**
   * Concats the distinct elements of `ys` onto the end of the `xs`, but also mutates the first.
   */
  public static <T> List<T> mutatingConcatDistinct(@NonNull final List<T> xs, @NonNull final List<T> ys) {
    for (final T y : ys) {
      if (! xs.contains(y)) {
        xs.add(y);
      }
    }
    return xs;
  }

  /**
   * Concats the distinct elements of `ys` onto the end of the `xs` without mutating either list.
   */
  public static <T> List<T> concatDistinct(@NonNull final List<T> xs, @NonNull final List<T> ys) {
    final List<T> zs = new ArrayList<>(xs);
    ListUtils.mutatingConcatDistinct(zs, ys);
    return zs;
  }

  /**
   * Prepends `x` to the beginning of the list `xs`.
   */
  public static <T> List<T> prepend(@NonNull final List<T> xs, @NonNull final T x) {
    final List<T> ys = new ArrayList<>(xs);
    ys.add(0, x);
    return ys;
  }

  /**
   * Appends `x` to the end of the list `xs`.
   */
  public static <T> List<T> append(@NonNull final List<T> xs, @NonNull final T x) {
    final List<T> ys = new ArrayList<>(xs);
    ys.add(x);
    return ys;
  }

  /**
   * Returns the first object or `null` if empty.
   */
  @Nullable public static <T> T first(@NonNull final List<T> xs) {
    return xs.size() > 0 ? xs.get(0) : null;
  }
}

@@ -2204,11 +2204,477 @@
 ull;%0A  %7D
+%0A%0A  /**%0A   * Uses Fisher-Yates algorithm to shuffle an array.%0A   * http://www.dotnetperls.com/shuffle-java%0A   */%0A  public static %3CT%3E List%3CT%3E shuffle(final @NonNull List%3CT%3E xs) %7B%0A    final List%3CT%3E ys = new ArrayList%3C%3E(xs);%0A    final int length = ys.size();%0A%0A    for (int i = 0; i %3C length; i++) %7B%0A      final int j = i + (int) (Math.random() * (length - i));%0A      final T temp = ys.get(i);%0A      ys.set(i, ys.get(j));%0A      ys.set(j, temp);%0A    %7D%0A%0A    return ys;%0A  %7D
 %0A%7D%0A

add Fisher-Yates shuffling to list utils