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

import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

public class IterableUtils {

  public static <S, T> boolean allIdentical(Iterable<S> iterable) {
    return allIdentical(iterable, Function.identity());
  }

  public static <S, T> boolean allIdentical(Iterable<S> iterable, Function<S, T> fn) {
    Iterator<S> iterator = iterable.iterator();
    if (!iterator.hasNext()) {
      return true;
    }
    T first = fn.apply(iterator.next());
    while (iterator.hasNext()) {
      T other = fn.apply(iterator.next());
      if (other != first) {
        return false;
      }
    }
    return true;
  }

  public static <S, T> boolean any(
      Iterable<S> iterable, Function<S, T> transform, Predicate<T> predicate) {
    for (S element : iterable) {
      if (predicate.test(transform.apply(element))) {
        return true;
      }
    }
    return false;
  }

  public static <T> Iterable<T> append(Iterable<T> iterable, T element) {
    return Iterables.concat(iterable, singleton(element));
  }

  public static <T> List<T> ensureUnmodifiableList(Iterable<T> iterable) {
    List<T> list;
    if (iterable instanceof List<?>) {
      list = (List<T>) iterable;
    } else {
      list = toNewArrayList(iterable);
    }
    return Collections.unmodifiableList(list);
  }

  public static <T> T findOrDefault(Iterable<T> iterable, Predicate<T> predicate, T defaultValue) {
    for (T element : iterable) {
      if (predicate.test(element)) {
        return element;
      }
    }
    return defaultValue;
  }

  public static <T> T first(Iterable<T> iterable) {
    return iterable.iterator().next();
  }

  public static <T> int firstIndexMatching(Iterable<T> iterable, Predicate<T> tester) {
    int i = 0;
    for (T element : iterable) {
      if (tester.test(element)) {
        return i;
      }
      i++;
    }
    return -1;
  }

  public static <T> Iterable<T> filter(Iterable<T> iterable, Predicate<? super T> predicate) {
    return () -> IteratorUtils.filter(iterable.iterator(), predicate);
  }

  public static <T> boolean hasNext(Iterable<T> iterable) {
    return iterable.iterator().hasNext();
  }

  public static <T> T min(Iterable<T> iterable, Comparator<T> comparator) {
    T min = null;
    for (T element : iterable) {
      if (min == null || comparator.compare(element, min) < 0) {
        min = element;
      }
    }
    return min;
  }

  public static <T> int size(Iterable<T> iterable) {
    int result = 0;
    for (T element : iterable) {
      result++;
    }
    return result;
  }

  public static <T> List<T> toNewArrayList(Iterable<T> iterable) {
    List<T> result = new ArrayList<>();
    iterable.forEach(result::add);
    return result;
  }

  public static <S, T> Iterable<T> transform(Iterable<S> iterable, Function<S, T> fn) {
    return Iterables.transform(iterable, fn::apply);
  }

  public static <T> boolean isEmpty(Iterable<T> iterable) {
    return !iterable.iterator().hasNext();
  }

  public static <T> Iterable<T> singleton(T element) {
    return () -> Iterators.singletonIterator(element);
  }

  public static <T> Iterable<T> prependSingleton(T t, Iterable<T> iterable) {
    return Iterables.concat(singleton(t), iterable);
  }

  public static <T> T reduce(T init, BiFunction<T, T, T> combine, Iterable<? extends T> iterable) {
    T v = init;
    for (T t : iterable) {
      v = combine.apply(v, t);
    }
    return v;
  }

  public static int sumInt(Iterable<Integer> iterable) {
    return reduce(0, Integer::sum, iterable);
  }

  public static <F> int sumInt(Iterable<F> iterable, Function<? super F, Integer> fn) {
    Iterable<Integer> integers = Iterables.transform(iterable, fn::apply);
    return sumInt(integers);
  }

  public static <T> Iterable<T> flatten(Iterable<? extends Iterable<T>> iterable) {
    return flatMap(iterable, Function.identity());
  }

  public static <T, U> Iterable<U> flatMap(
      Iterable<T> iterable, Function<? super T, Iterable<U>> map) {
    return Iterables.concat(Iterables.transform(iterable, map::apply));
  }

  public static <T> Iterable<T> empty() {
    return Collections.emptyList();
  }

  public static <T> Iterable<T> emptyIf(Iterable<T> iterable, boolean condition) {
    if (condition) {
      return Collections.emptySet();
    } else {
      return iterable;
    }
  }

  /**
   * Utility method for testing the the elements in one and other pair-wise. Returns false if the
   * lengths differ.
   */
  public static <T> boolean testPairs(
      BiPredicate<T, T> predicate, Iterable<T> one, Iterable<T> other) {
    Iterator<T> iterator = other.iterator();
    for (T first : one) {
      if (!iterator.hasNext()) {
        return false;
      }
      T second = iterator.next();
      if (!predicate.test(first, second)) {
        return false;
      }
    }
    return !iterator.hasNext();
  }

  public static <T, R> Iterable<R> fromMethod(Consumer<Consumer<T>> method, Function<T, R> mapper) {
    List<R> ts = new ArrayList<>();
    method.accept(t -> ts.add(mapper.apply(t)));
    return ts;
  }
}
