/*
 * 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 | Spliterator.SUBSIZED));
      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;
  }
}
