/// Created by @Haoyi on 2021/7/7

part of "extensions.dart";

extension ListExtension<T> on Iterable<T> {
  T? get safeLast => isEmpty ? null : last;

  T? get safeFirst => isEmpty ? null : first;

  int get lastIndex => length - 1;

  List<T> get filterOutNulls {
    final List<T> filtered = [];
    for (var item in this) {
      if (item != null) {
        filtered.add(item);
      }
    }
    return filtered;
  }

  T? firstWhereOrNull(bool Function(T element) test, {T? Function()? orElse}) {
    for (T element in this) {
      if (test(element)) return element;
    }
    if (orElse != null) return orElse();
    return null;
  }

  T? firstOrNull() {
    return isNotEmpty ? first : null;
  }

  /// The first element whose value and index satisfies [test].
  ///
  /// Returns `null` if there are no element and index satisfying [test].
  T? firstWhereIndexedOrNull(bool Function(int index, T element) test) {
    var index = 0;
    for (var element in this) {
      if (test(index++, element)) return element;
    }
    return null;
  }

  /// The last element satisfying [test], or `null` if there are none.
  T? lastWhereOrNull(bool Function(T element) test) {
    T? result;
    for (var element in this) {
      if (test(element)) result = element;
    }
    return result;
  }

  /// The last element whose index and value satisfies [test].
  ///
  /// Returns `null` if no element and index satisfies [test].
  T? lastWhereIndexedOrNull(bool Function(int index, T element) test) {
    T? result;
    var index = 0;
    for (var element in this) {
      if (test(index++, element)) result = element;
    }
    return result;
  }

  /// The last element, or `null` if the iterable is empty.
  T? get lastOrNull {
    if (isEmpty) return null;
    return last;
  }
}
