/*
 * Copyright 2016 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package java.util.stream;

import static javaemul.internal.InternalPreconditions.checkNotNull;
import static javaemul.internal.InternalPreconditions.checkState;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.Spliterators.AbstractDoubleSpliterator;
import java.util.Spliterators.AbstractIntSpliterator;
import java.util.Spliterators.AbstractLongSpliterator;
import java.util.Spliterators.AbstractSpliterator;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.DoubleConsumer;
import java.util.function.Function;
import java.util.function.IntConsumer;
import java.util.function.IntFunction;
import java.util.function.LongConsumer;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.ToDoubleFunction;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;

/**
 * Main implementation of Stream, wrapping a single spliterator and an optional parent stream.
 */
final class StreamImpl<T> extends TerminatableStream<StreamImpl<T>> implements Stream<T> {

  /**
   * Represents an empty stream, doing nothing for all methods.
   */
  static class Empty<T> extends TerminatableStream<Empty<T>> implements Stream<T> {

    public Empty(TerminatableStream<?> previous) {
      super(previous);
    }

    @Override
    public Stream<T> filter(Predicate<? super T> predicate) {
      throwIfTerminated();
      return this;
    }

    @Override
    public <R> Stream<R> map(Function<? super T, ? extends R> mapper) {
      throwIfTerminated();
      return (Stream) this;
    }

    @Override
    public IntStream mapToInt(ToIntFunction<? super T> mapper) {
      throwIfTerminated();
      return new IntStreamImpl.Empty(this);
    }

    @Override
    public LongStream mapToLong(ToLongFunction<? super T> mapper) {
      throwIfTerminated();
      return new LongStreamImpl.Empty(this);
    }

    @Override
    public DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper) {
      throwIfTerminated();
      return new DoubleStreamImpl.Empty(this);
    }

    @Override
    public <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper) {
      throwIfTerminated();
      return (Stream) this;
    }

    @Override
    public IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper) {
      throwIfTerminated();
      return new IntStreamImpl.Empty(this);
    }

    @Override
    public LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper) {
      throwIfTerminated();
      return new LongStreamImpl.Empty(this);
    }

    @Override
    public DoubleStream flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper) {
      throwIfTerminated();
      return new DoubleStreamImpl.Empty(this);
    }

    @Override
    public Stream<T> distinct() {
      throwIfTerminated();
      return this;
    }

    @Override
    public Stream<T> sorted() {
      throwIfTerminated();
      return this;
    }

    @Override
    public Stream<T> sorted(Comparator<? super T> comparator) {
      throwIfTerminated();
      return this;
    }

    @Override
    public Stream<T> peek(Consumer<? super T> action) {
      throwIfTerminated();
      return this;
    }

    @Override
    public Stream<T> limit(long maxSize) {
      throwIfTerminated();
      checkState(maxSize >= 0, "maxSize may not be negative");
      return this;
    }

    @Override
    public Stream<T> skip(long n) {
      throwIfTerminated();
      checkState(n >= 0, "n may not be negative");
      return this;
    }

    @Override
    public void forEach(Consumer<? super T> action) {
      terminate();
      // nothing to do
    }

    @Override
    public void forEachOrdered(Consumer<? super T> action) {
      terminate();
      // nothing to do
    }

    @Override
    public Object[] toArray() {
      terminate();
      return new Object[0];
    }

    @Override
    public <A> A[] toArray(IntFunction<A[]> generator) {
      terminate();
      return generator.apply(0);
    }

    @Override
    public T reduce(T identity, BinaryOperator<T> accumulator) {
      terminate();
      return identity;
    }

    @Override
    public Optional<T> reduce(BinaryOperator<T> accumulator) {
      terminate();
      return Optional.empty();
    }

    @Override
    public <U> U reduce(
        U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner) {
      terminate();
      return identity;
    }

    @Override
    public <R> R collect(
        Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner) {
      terminate();
      return supplier.get();
    }

    @Override
    public <R, A> R collect(Collector<? super T, A, R> collector) {
      terminate();
      return collector.finisher().apply(collector.supplier().get());
    }

    @Override
    public Optional<T> min(Comparator<? super T> comparator) {
      terminate();
      return Optional.empty();
    }

    @Override
    public Optional<T> max(Comparator<? super T> comparator) {
      terminate();
      return Optional.empty();
    }

    @Override
    public long count() {
      terminate();
      return 0;
    }

    @Override
    public boolean anyMatch(Predicate<? super T> predicate) {
      terminate();
      return false;
    }

    @Override
    public boolean allMatch(Predicate<? super T> predicate) {
      terminate();
      return true;
    }

    @Override
    public boolean noneMatch(Predicate<? super T> predicate) {
      terminate();
      return true;
    }

    @Override
    public Optional<T> findFirst() {
      terminate();
      return Optional.empty();
    }

    @Override
    public Optional<T> findAny() {
      terminate();
      return Optional.empty();
    }

    @Override
    public Iterator<T> iterator() {
      terminate();
      return Collections.emptyIterator();
    }

    @Override
    public Spliterator<T> spliterator() {
      terminate();
      return Spliterators.emptySpliterator();
    }

    @Override
    public boolean isParallel() {
      throwIfTerminated();
      return false;
    }

    @Override
    public Stream<T> sequential() {
      throwIfTerminated();
      return this;
    }

    @Override
    public Stream<T> parallel() {
      throwIfTerminated();
      return this;
    }

    @Override
    public Stream<T> unordered() {
      throwIfTerminated();
      return this;
    }
  }

  /**
   * Object to Object map spliterator.
   *
   * @param <U> the input type
   * @param <T> the output type
   */
  private static final class MapToObjSpliterator<U, T> extends Spliterators.AbstractSpliterator<T> {
    private final Function<? super U, ? extends T> map;
    private final Spliterator<U> original;

    public MapToObjSpliterator(Function<? super U, ? extends T> map, Spliterator<U> original) {
      super(
          original.estimateSize(),
          original.characteristics() & ~(Spliterator.SORTED | Spliterator.DISTINCT));
      checkNotNull(map);
      this.map = map;
      this.original = original;
    }

    @Override
    public boolean tryAdvance(final Consumer<? super T> action) {
      return original.tryAdvance(u -> action.accept(map.apply(u)));
    }
  }

  /**
   * Object to Int map spliterator.
   *
   * @param <T> the input type
   */
  private static final class MapToIntSpliterator<T> extends Spliterators.AbstractIntSpliterator {
    private final ToIntFunction<? super T> map;
    private final Spliterator<T> original;

    public MapToIntSpliterator(ToIntFunction<? super T> map, Spliterator<T> original) {
      super(
          original.estimateSize(),
          original.characteristics() & ~(Spliterator.SORTED | Spliterator.DISTINCT));
      checkNotNull(map);
      this.map = map;
      this.original = original;
    }

    @Override
    public boolean tryAdvance(final IntConsumer action) {
      return original.tryAdvance(u -> action.accept(map.applyAsInt(u)));
    }
  }

  /**
   * Object to Long map spliterator.
   *
   * @param <T> the input type
   */
  private static final class MapToLongSpliterator<T> extends Spliterators.AbstractLongSpliterator {
    private final ToLongFunction<? super T> map;
    private final Spliterator<T> original;

    public MapToLongSpliterator(ToLongFunction<? super T> map, Spliterator<T> original) {
      super(
          original.estimateSize(),
          original.characteristics() & ~(Spliterator.SORTED | Spliterator.DISTINCT));
      checkNotNull(map);
      this.map = map;
      this.original = original;
    }

    @Override
    public boolean tryAdvance(final LongConsumer action) {
      return original.tryAdvance(u -> action.accept(map.applyAsLong(u)));
    }
  }

  /**
   * Object to Double map spliterator.
   *
   * @param <T> the input type
   */
  private static final class MapToDoubleSpliterator<T>
      extends Spliterators.AbstractDoubleSpliterator {
    private final ToDoubleFunction<? super T> map;
    private final Spliterator<T> original;

    public MapToDoubleSpliterator(ToDoubleFunction<? super T> map, Spliterator<T> original) {
      super(
          original.estimateSize(),
          original.characteristics() & ~(Spliterator.SORTED | Spliterator.DISTINCT));
      checkNotNull(map);
      this.map = map;
      this.original = original;
    }

    @Override
    public boolean tryAdvance(final DoubleConsumer action) {
      return original.tryAdvance(u -> action.accept(map.applyAsDouble(u)));
    }
  }

  /**
   * Object filter spliterator.
   *
   * @param <T> the type of data to iterate over
   */
  private static final class FilterSpliterator<T> extends Spliterators.AbstractSpliterator<T> {
    private final Predicate<? super T> filter;
    private final Spliterator<T> original;

    private boolean found;

    public FilterSpliterator(Predicate<? super T> filter, Spliterator<T> original) {
      super(original.estimateSize(), original.characteristics() & ~Spliterator.SIZED);
      checkNotNull(filter);
      this.filter = filter;
      this.original = original;
    }

    @Override
    public Comparator<? super T> getComparator() {
      return original.getComparator();
    }

    @Override
    public boolean tryAdvance(final Consumer<? super T> action) {
      found = false;
      while (!found
          && original.tryAdvance(
              item -> {
                if (filter.test(item)) {
                  found = true;
                  action.accept(item);
                }
              })) {
        // do nothing, work is done in tryAdvance
      }

      return found;
    }
  }

  /**
   * Object skip spliterator.
   *
   * @param <T> the type of data to iterate over
   */
  private static final class SkipSpliterator<T> extends Spliterators.AbstractSpliterator<T> {
    private long skip;
    private final Spliterator<T> original;

    public SkipSpliterator(long skip, Spliterator<T> original) {
      super(
          original.hasCharacteristics(Spliterator.SIZED)
              ? Math.max(0, original.estimateSize() - skip)
              : Long.MAX_VALUE,
          original.characteristics());
      this.skip = skip;
      this.original = original;
    }

    @Override
    public Comparator<? super T> getComparator() {
      return original.getComparator();
    }

    @Override
    public boolean tryAdvance(Consumer<? super T> action) {
      while (skip > 0) {
        if (!original.tryAdvance(ignore -> { })) {
          return false;
        }
        skip--;
      }
      return original.tryAdvance(action);
    }
  }

  /**
   * Object limit spliterator.
   *
   * @param <T> the type of data to iterate over
   */
  private static final class LimitSpliterator<T> extends Spliterators.AbstractSpliterator<T> {
    private final long limit;
    private final Spliterator<T> original;
    private int position = 0;

    public LimitSpliterator(long limit, Spliterator<T> original) {
      super(
          original.hasCharacteristics(Spliterator.SIZED)
              ? Math.min(original.estimateSize(), limit)
              : Long.MAX_VALUE,
          original.characteristics());
      this.limit = limit;
      this.original = original;
    }

    @Override
    public Comparator<? super T> getComparator() {
      return original.getComparator();
    }

    @Override
    public boolean tryAdvance(Consumer<? super T> action) {
      if (position >= limit) {
        return false;
      }
      boolean result = original.tryAdvance(action);
      position++;
      return result;
    }
  }

  /**
   * Value holder for various stream operations.
   */
  private static final class ValueConsumer<T> implements Consumer<T> {
    T value;

    @Override
    public void accept(T value) {
      this.value = value;
    }
  }

  private final Spliterator<T> spliterator;

  public StreamImpl(TerminatableStream<?> prev, Spliterator<T> spliterator) {
    super(prev);
    this.spliterator = spliterator;
  }

  // terminal
  @Override
  public Spliterator<T> spliterator() {
    terminate();
    return spliterator;
  }

  @Override
  public Iterator<T> iterator() {
    return Spliterators.iterator(spliterator());
  }

  @Override
  public long count() {
    terminate();
    long count = 0;
    while (spliterator.tryAdvance(a -> { })) {
      count++;
    }
    return count;
  }

  @Override
  public void forEach(Consumer<? super T> action) {
    forEachOrdered(action);
  }

  @Override
  public void forEachOrdered(Consumer<? super T> action) {
    terminate();
    spliterator.forEachRemaining(action);
  }

  @Override
  public Object[] toArray() {
    return toArray(Object[]::new);
  }

  @Override
  public <A> A[] toArray(IntFunction<A[]> generator) {
    List<T> collected = collect(Collectors.toList());
    return collected.toArray(generator.apply(collected.size()));
  }

  @Override
  public <R> R collect(
      Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner) {
    return collect(
        Collector.of(
            supplier,
            accumulator,
            (a, b) -> {
              combiner.accept(a, b);
              return a;
            }));
  }

  @Override
  public <R, A> R collect(final Collector<? super T, A, R> collector) {
    return collector
        .finisher()
        .apply(
            reduce(
                collector.supplier().get(),
                (a, t) -> {
                  collector.accumulator().accept(a, t);
                  return a;
                },
                collector.combiner()));
  }

  @Override
  public Optional<T> findFirst() {
    terminate();
    ValueConsumer<T> holder = new ValueConsumer<T>();
    if (spliterator.tryAdvance(holder)) {
      return Optional.of(holder.value);
    }
    return Optional.empty();
  }

  @Override
  public Optional<T> findAny() {
    return findFirst();
  }

  private static final Consumer<Object> NULL_CONSUMER = value -> { };

  @Override
  public boolean anyMatch(Predicate<? super T> predicate) {
    return filter(predicate).spliterator().tryAdvance(NULL_CONSUMER);
  }

  @Override
  public boolean allMatch(final Predicate<? super T> predicate) {
    return !anyMatch(predicate.negate());
  }

  @Override
  public boolean noneMatch(final Predicate<? super T> predicate) {
    return !anyMatch(predicate);
  }

  @Override
  public Optional<T> min(final Comparator<? super T> comparator) {
    return reduce(BinaryOperator.minBy(comparator));
  }

  @Override
  public Optional<T> max(final Comparator<? super T> comparator) {
    return reduce(BinaryOperator.maxBy(comparator));
  }

  @Override
  public T reduce(T identity, BinaryOperator<T> accumulator) {
    return reduce(identity, accumulator, accumulator);
  }

  @Override
  public Optional<T> reduce(BinaryOperator<T> accumulator) {
    ValueConsumer<T> consumer = new ValueConsumer<T>();
    if (!spliterator.tryAdvance(consumer)) {
      terminate();
      return Optional.empty();
    }
    return Optional.of(reduce(consumer.value, accumulator));
  }

  // combiner is ignored, since we don't parallelize
  @Override
  public <U> U reduce(
      U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner) {
    terminate();
    final ValueConsumer<U> consumer = new ValueConsumer<U>();
    consumer.value = identity;
    spliterator.forEachRemaining(
        item -> {
          consumer.accept(accumulator.apply(consumer.value, item));
        });
    return consumer.value;
  }
  // end terminal

  // intermediate
  @Override
  public Stream<T> filter(Predicate<? super T> predicate) {
    throwIfTerminated();
    return new StreamImpl<>(this, new FilterSpliterator<>(predicate, spliterator));
  }

  @Override
  public <R> Stream<R> map(Function<? super T, ? extends R> mapper) {
    throwIfTerminated();
    return new StreamImpl<>(this, new MapToObjSpliterator<>(mapper, spliterator));
  }

  @Override
  public IntStream mapToInt(ToIntFunction<? super T> mapper) {
    throwIfTerminated();
    return new IntStreamImpl(this, new MapToIntSpliterator<>(mapper, spliterator));
  }

  @Override
  public LongStream mapToLong(ToLongFunction<? super T> mapper) {
    throwIfTerminated();
    return new LongStreamImpl(this, new MapToLongSpliterator<>(mapper, spliterator));
  }

  @Override
  public DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper) {
    throwIfTerminated();
    return new DoubleStreamImpl(this, new MapToDoubleSpliterator<>(mapper, spliterator));
  }

  @Override
  public <R> Stream<R> flatMap(final Function<? super T, ? extends Stream<? extends R>> mapper) {
    throwIfTerminated();
    final Spliterator<? extends Stream<? extends R>> spliteratorOfStreams =
        new MapToObjSpliterator<>(mapper, spliterator);

    AbstractSpliterator<R> flatMapSpliterator =
        new Spliterators.AbstractSpliterator<R>(Long.MAX_VALUE, 0) {
          Stream<? extends R> nextStream;
          Spliterator<? extends R> next;

          @Override
          public boolean tryAdvance(Consumer<? super R> action) {
            // look for a new spliterator
            while (advanceToNextSpliterator()) {
              // if we have one, try to read and use it
              if (next.tryAdvance(action)) {
                return true;
              } else {
                nextStream.close();
                nextStream = null;
                // failed, null it out so we can find another
                next = null;
              }
            }
            return false;
          }

          private boolean advanceToNextSpliterator() {
            while (next == null) {
              if (!spliteratorOfStreams.tryAdvance(
                  n -> {
                    if (n != null) {
                      nextStream = n;
                      next = n.spliterator();
                    }
                  })) {
                return false;
              }
            }
            return true;
          }
        };

    return new StreamImpl<R>(this, flatMapSpliterator);
  }

  @Override
  public IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper) {
    throwIfTerminated();
    final Spliterator<? extends IntStream> spliteratorOfStreams =
        new MapToObjSpliterator<>(mapper, spliterator);

    AbstractIntSpliterator flatMapSpliterator =
        new Spliterators.AbstractIntSpliterator(Long.MAX_VALUE, 0) {
          IntStream nextStream;
          Spliterator.OfInt next;

          @Override
          public boolean tryAdvance(IntConsumer action) {
            // look for a new spliterator
            while (advanceToNextSpliterator()) {
              // if we have one, try to read and use it
              if (next.tryAdvance(action)) {
                return true;
              } else {
                nextStream.close();
                nextStream = null;
                // failed, null it out so we can find another
                next = null;
              }
            }
            return false;
          }

          private boolean advanceToNextSpliterator() {
            while (next == null) {
              if (!spliteratorOfStreams.tryAdvance(
                  n -> {
                    if (n != null) {
                      nextStream = n;
                      next = n.spliterator();
                    }
                  })) {
                return false;
              }
            }
            return true;
          }
        };

    return new IntStreamImpl(this, flatMapSpliterator);
  }

  @Override
  public LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper) {
    throwIfTerminated();
    final Spliterator<? extends LongStream> spliteratorOfStreams =
        new MapToObjSpliterator<>(mapper, spliterator);

    AbstractLongSpliterator flatMapSpliterator =
        new Spliterators.AbstractLongSpliterator(Long.MAX_VALUE, 0) {
          LongStream nextStream;
          Spliterator.OfLong next;

          @Override
          public boolean tryAdvance(LongConsumer action) {
            // look for a new spliterator
            while (advanceToNextSpliterator()) {
              // if we have one, try to read and use it
              if (next.tryAdvance(action)) {
                return true;
              } else {
                nextStream.close();
                nextStream = null;
                // failed, null it out so we can find another
                next = null;
              }
            }
            return false;
          }

          private boolean advanceToNextSpliterator() {
            while (next == null) {
              if (!spliteratorOfStreams.tryAdvance(
                  n -> {
                    if (n != null) {
                      nextStream = n;
                      next = n.spliterator();
                    }
                  })) {
                return false;
              }
            }
            return true;
          }
        };

    return new LongStreamImpl(this, flatMapSpliterator);
  }

  @Override
  public DoubleStream flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper) {
    throwIfTerminated();
    final Spliterator<? extends DoubleStream> spliteratorOfStreams =
        new MapToObjSpliterator<>(mapper, spliterator);

    AbstractDoubleSpliterator flatMapSpliterator =
        new Spliterators.AbstractDoubleSpliterator(Long.MAX_VALUE, 0) {
          DoubleStream nextStream;
          Spliterator.OfDouble next;

          @Override
          public boolean tryAdvance(DoubleConsumer action) {
            // look for a new spliterator
            while (advanceToNextSpliterator()) {
              // if we have one, try to read and use it
              if (next.tryAdvance(action)) {
                return true;
              } else {
                nextStream.close();
                nextStream = null;
                // failed, null it out so we can find another
                next = null;
              }
            }
            return false;
          }

          private boolean advanceToNextSpliterator() {
            while (next == null) {
              if (!spliteratorOfStreams.tryAdvance(
                  n -> {
                    if (n != null) {
                      nextStream = n;
                      next = n.spliterator();
                    }
                  })) {
                return false;
              }
            }
            return true;
          }
        };

    return new DoubleStreamImpl(this, flatMapSpliterator);
  }

  @Override
  public Stream<T> distinct() {
    throwIfTerminated();
    HashSet<T> seen = new HashSet<>();
    return filter(seen::add);
  }

  @Override
  public Stream<T> sorted() {
    throwIfTerminated();
    Comparator<T> c = (Comparator) Comparator.naturalOrder();
    return sorted(c);
  }

  @Override
  public Stream<T> sorted(final Comparator<? super T> comparator) {
    throwIfTerminated();

    AbstractSpliterator<T> sortedSpliterator =
        new Spliterators.AbstractSpliterator<T>(
            spliterator.estimateSize(), spliterator.characteristics() | Spliterator.SORTED) {
          Spliterator<T> ordered = null;

          @Override
          public Comparator<? super T> getComparator() {
            return comparator == Comparator.naturalOrder() ? null : comparator;
          }

          @Override
          public boolean tryAdvance(Consumer<? super T> action) {
            if (ordered == null) {
              List<T> list = new ArrayList<>();
              spliterator.forEachRemaining(list::add);
              Collections.sort(list, comparator);
              ordered = list.spliterator();
            }
            return ordered.tryAdvance(action);
          }
        };

    return new StreamImpl<>(this, sortedSpliterator);
  }

  @Override
  public Stream<T> peek(final Consumer<? super T> action) {
    checkNotNull(action);
    throwIfTerminated();

    AbstractSpliterator<T> peekSpliterator =
        new Spliterators.AbstractSpliterator<T>(
            spliterator.estimateSize(), spliterator.characteristics()) {
          @Override
          public boolean tryAdvance(final Consumer<? super T> innerAction) {
            return spliterator.tryAdvance(
                item -> {
                  action.accept(item);
                  innerAction.accept(item);
                });
          }
        };

    return new StreamImpl<>(this, peekSpliterator);
  }

  @Override
  public Stream<T> limit(long maxSize) {
    throwIfTerminated();
    checkState(maxSize >= 0, "maxSize may not be negative");
    return new StreamImpl<>(this, new LimitSpliterator<>(maxSize, spliterator));
  }

  @Override
  public Stream<T> skip(long n) {
    throwIfTerminated();
    checkState(n >= 0, "n may not be negative");
    if (n == 0) {
      return this;
    }
    return new StreamImpl<>(this, new SkipSpliterator<>(n, spliterator));
  }

  @Override
  public boolean isParallel() {
    throwIfTerminated();
    return false;
  }

  @Override
  public Stream<T> sequential() {
    throwIfTerminated();
    return this;
  }

  @Override
  public Stream<T> parallel() {
    throwIfTerminated();
    // do nothing, no such thing as gwt+parallel
    return this;
  }

  @Override
  public Stream<T> unordered() {
    throwIfTerminated();
    return this;
  }
}
