/*
 * 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.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LongSummaryStatistics;
import java.util.OptionalDouble;
import java.util.OptionalLong;
import java.util.PrimitiveIterator;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.Spliterators.AbstractLongSpliterator;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.DoubleConsumer;
import java.util.function.IntConsumer;
import java.util.function.LongBinaryOperator;
import java.util.function.LongConsumer;
import java.util.function.LongFunction;
import java.util.function.LongPredicate;
import java.util.function.LongToDoubleFunction;
import java.util.function.LongToIntFunction;
import java.util.function.LongUnaryOperator;
import java.util.function.ObjLongConsumer;
import java.util.function.Supplier;

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

  /**
   * Represents an empty stream, doing nothing for all methods.
   */
  static class Empty extends TerminatableStream<Empty> implements LongStream {
    public Empty(TerminatableStream<?> previous) {
      super(previous);
    }

    @Override
    public LongStream filter(LongPredicate predicate) {
      throwIfTerminated();
      return this;
    }

    @Override
    public LongStream map(LongUnaryOperator mapper) {
      throwIfTerminated();
      return this;
    }

    @Override
    public <U> Stream<U> mapToObj(LongFunction<? extends U> mapper) {
      throwIfTerminated();
      return new StreamImpl.Empty<U>(this);
    }

    @Override
    public IntStream mapToInt(LongToIntFunction mapper) {
      throwIfTerminated();
      return new IntStreamImpl.Empty(this);
    }

    @Override
    public DoubleStream mapToDouble(LongToDoubleFunction mapper) {
      throwIfTerminated();
      return new DoubleStreamImpl.Empty(this);
    }

    @Override
    public LongStream flatMap(LongFunction<? extends LongStream> mapper) {
      throwIfTerminated();
      return this;
    }

    @Override
    public LongStream distinct() {
      throwIfTerminated();
      return this;
    }

    @Override
    public LongStream sorted() {
      throwIfTerminated();
      return this;
    }

    @Override
    public LongStream peek(LongConsumer action) {
      throwIfTerminated();
      return this;
    }

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

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

    @Override
    public void forEach(LongConsumer action) {
      terminate();
    }

    @Override
    public void forEachOrdered(LongConsumer action) {
      terminate();
    }

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

    @Override
    public long reduce(long identity, LongBinaryOperator op) {
      terminate();
      return identity;
    }

    @Override
    public OptionalLong reduce(LongBinaryOperator op) {
      terminate();
      return OptionalLong.empty();
    }

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

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

    @Override
    public OptionalLong min() {
      terminate();
      return OptionalLong.empty();
    }

    @Override
    public OptionalLong max() {
      terminate();
      return OptionalLong.empty();
    }

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

    @Override
    public OptionalDouble average() {
      terminate();
      return OptionalDouble.empty();
    }

    @Override
    public LongSummaryStatistics summaryStatistics() {
      terminate();
      return new LongSummaryStatistics();
    }

    @Override
    public boolean anyMatch(LongPredicate predicate) {
      terminate();
      return false;
    }

    @Override
    public boolean allMatch(LongPredicate predicate) {
      terminate();
      return true;
    }

    @Override
    public boolean noneMatch(LongPredicate predicate) {
      terminate();
      return true;
    }

    @Override
    public OptionalLong findFirst() {
      terminate();
      return OptionalLong.empty();
    }

    @Override
    public OptionalLong findAny() {
      terminate();
      return OptionalLong.empty();
    }

    @Override
    public DoubleStream asDoubleStream() {
      throwIfTerminated();
      return new DoubleStreamImpl.Empty(this);
    }

    @Override
    public Stream<Long> boxed() {
      throwIfTerminated();
      return new StreamImpl.Empty<Long>(this);
    }

    @Override
    public LongStream sequential() {
      throwIfTerminated();
      return this;
    }

    @Override
    public LongStream parallel() {
      throwIfTerminated();
      return this;
    }

    @Override
    public PrimitiveIterator.OfLong iterator() {
      return Spliterators.iterator(spliterator());
    }

    @Override
    public Spliterator.OfLong spliterator() {
      terminate();
      return Spliterators.emptyLongSpliterator();
    }

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

    @Override
    public LongStream unordered() {
      throwIfTerminated();
      return this;
    }
  }

  /**
   * Long to Int map spliterator.
   */
  private static final class MapToIntSpliterator extends Spliterators.AbstractIntSpliterator {
    private final LongToIntFunction map;
    private final Spliterator.OfLong original;

    public MapToIntSpliterator(LongToIntFunction map, Spliterator.OfLong 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((long u) -> action.accept(map.applyAsInt(u)));
    }
  }

  /**
   * Long to Object map spliterator.
   *
   * @param <T> the type of data in the object spliterator
   */
  private static final class MapToObjSpliterator<T> extends Spliterators.AbstractSpliterator<T> {
    private final LongFunction<? extends T> map;
    private final Spliterator.OfLong original;

    public MapToObjSpliterator(LongFunction<? extends T> map, Spliterator.OfLong 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((long u) -> action.accept(map.apply(u)));
    }
  }

  /**
   * Long to Long map spliterator.
   */
  private static final class MapToLongSpliterator extends Spliterators.AbstractLongSpliterator {
    private final LongUnaryOperator map;
    private final Spliterator.OfLong original;

    public MapToLongSpliterator(LongUnaryOperator map, Spliterator.OfLong 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((long u) -> action.accept(map.applyAsLong(u)));
    }
  }

  /**
   * Long to Double map Spliterator.
   */
  private static final class MapToDoubleSpliterator extends Spliterators.AbstractDoubleSpliterator {
    private final LongToDoubleFunction map;
    private final Spliterator.OfLong original;

    public MapToDoubleSpliterator(LongToDoubleFunction map, Spliterator.OfLong 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((long u) -> action.accept(map.applyAsDouble(u)));
    }
  }

  /**
   * Long filter spliterator.
   */
  private static final class FilterSpliterator extends Spliterators.AbstractLongSpliterator {
    private final LongPredicate filter;
    private final Spliterator.OfLong original;

    private boolean found;

    public FilterSpliterator(LongPredicate filter, Spliterator.OfLong original) {
      super(
          original.estimateSize(),
          original.characteristics() & ~(Spliterator.SIZED | Spliterator.SUBSIZED));
      checkNotNull(filter);
      this.filter = filter;
      this.original = original;
    }

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

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

      return found;
    }
  }

  /**
   * Long skip spliterator.
   */
  private static final class SkipSpliterator extends Spliterators.AbstractLongSpliterator {
    private long skip;
    private final Spliterator.OfLong original;

    public SkipSpliterator(long skip, Spliterator.OfLong 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 Long> getComparator() {
      return original.getComparator();
    }

    @Override
    public boolean tryAdvance(LongConsumer action) {
      while (skip > 0) {
        if (!original.tryAdvance((long ignore) -> { })) {
          return false;
        }
        skip--;
      }
      return original.tryAdvance(action);
    }
  }

  /**
   * Long limit spliterator.
   */
  private static final class LimitSpliterator extends Spliterators.AbstractLongSpliterator {
    private final long limit;
    private final Spliterator.OfLong original;
    private int position = 0;

    public LimitSpliterator(long limit, Spliterator.OfLong 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 Long> getComparator() {
      return original.getComparator();
    }

    @Override
    public boolean tryAdvance(LongConsumer 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 implements LongConsumer {
    long value;

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

  private final Spliterator.OfLong spliterator;

  public LongStreamImpl(TerminatableStream<?> previous, Spliterator.OfLong spliterator) {
    super(previous);
    this.spliterator = spliterator;
  }

  // terminals

  @Override
  public void forEach(LongConsumer action) {
    forEachOrdered(action);
  }

  @Override
  public void forEachOrdered(LongConsumer action) {
    terminate();
    spliterator.forEachRemaining(action);
  }

  @Override
  public long[] toArray() {
    terminate();
    long[] entries = new long[0];
    // this is legal in js, since the array will be backed by a JS array
    spliterator.forEachRemaining((long value) -> entries[entries.length] = value);

    return entries;
  }

  @Override
  public long reduce(long identity, LongBinaryOperator op) {
    terminate();
    ValueConsumer holder = new ValueConsumer();
    holder.value = identity;
    spliterator.forEachRemaining(
        (long value) -> {
          holder.accept(op.applyAsLong(holder.value, value));
        });
    return holder.value;
  }

  @Override
  public OptionalLong reduce(LongBinaryOperator op) {
    ValueConsumer holder = new ValueConsumer();
    if (spliterator.tryAdvance(holder)) {
      return OptionalLong.of(reduce(holder.value, op));
    }
    terminate();
    return OptionalLong.empty();
  }

  @Override
  public <R> R collect(
      Supplier<R> supplier, ObjLongConsumer<R> accumulator, BiConsumer<R, R> combiner) {
    terminate();
    final R acc = supplier.get();
    spliterator.forEachRemaining((long value) -> accumulator.accept(acc, value));
    return acc;
  }

  @Override
  public long sum() {
    return summaryStatistics().getSum();
  }

  @Override
  public OptionalLong min() {
    LongSummaryStatistics stats = summaryStatistics();
    if (stats.getCount() == 0) {
      return OptionalLong.empty();
    }
    return OptionalLong.of(stats.getMin());
  }

  @Override
  public OptionalLong max() {
    LongSummaryStatistics stats = summaryStatistics();
    if (stats.getCount() == 0) {
      return OptionalLong.empty();
    }
    return OptionalLong.of(stats.getMax());
  }

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

  @Override
  public OptionalDouble average() {
    LongSummaryStatistics stats = summaryStatistics();
    if (stats.getCount() == 0) {
      return OptionalDouble.empty();
    }
    return OptionalDouble.of(stats.getAverage());
  }

  @Override
  public LongSummaryStatistics summaryStatistics() {
    return collect(
        LongSummaryStatistics::new,
        // TODO switch to a lambda reference once #9340 is fixed
        (longSummaryStatistics, value) -> longSummaryStatistics.accept(value),
        LongSummaryStatistics::combine);
  }

  @Override
  public boolean anyMatch(LongPredicate predicate) {
    return filter(predicate).findFirst().isPresent();
  }

  @Override
  public boolean allMatch(LongPredicate predicate) {
    return !anyMatch(predicate.negate());
  }

  @Override
  public boolean noneMatch(LongPredicate predicate) {
    return !anyMatch(predicate);
  }

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

  @Override
  public OptionalLong findAny() {
    return findFirst();
  }

  @Override
  public PrimitiveIterator.OfLong iterator() {
    return Spliterators.iterator(spliterator());
  }

  @Override
  public Spliterator.OfLong spliterator() {
    terminate();
    return spliterator;
  }
  // end terminals

  // intermediates
  @Override
  public LongStream filter(LongPredicate predicate) {
    throwIfTerminated();
    return new LongStreamImpl(this, new FilterSpliterator(predicate, spliterator));
  }

  @Override
  public LongStream map(LongUnaryOperator mapper) {
    throwIfTerminated();
    return new LongStreamImpl(this, new MapToLongSpliterator(mapper, spliterator));
  }

  @Override
  public <U> Stream<U> mapToObj(LongFunction<? extends U> mapper) {
    throwIfTerminated();
    return new StreamImpl<U>(this, new MapToObjSpliterator<U>(mapper, spliterator));
  }

  @Override
  public IntStream mapToInt(LongToIntFunction mapper) {
    throwIfTerminated();
    return new IntStreamImpl(this, new MapToIntSpliterator(mapper, spliterator));
  }

  @Override
  public DoubleStream mapToDouble(LongToDoubleFunction mapper) {
    throwIfTerminated();
    return new DoubleStreamImpl(this, new MapToDoubleSpliterator(mapper, spliterator));
  }

  @Override
  public LongStream flatMap(LongFunction<? 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 LongStream distinct() {
    throwIfTerminated();
    HashSet<Long> seen = new HashSet<>();
    return filter(seen::add);
  }

  @Override
  public LongStream sorted() {
    throwIfTerminated();

    AbstractLongSpliterator sortedSpliterator =
        new Spliterators.AbstractLongSpliterator(
            spliterator.estimateSize(), spliterator.characteristics() | Spliterator.SORTED) {
          Spliterator.OfLong ordered = null;

          @Override
          public Comparator<? super Long> getComparator() {
            return null;
          }

          @Override
          public boolean tryAdvance(LongConsumer action) {
            if (ordered == null) {
              long[] list = new long[0];
              spliterator.forEachRemaining((long item) -> list[list.length] = item);
              Arrays.sort(list);
              ordered = Spliterators.spliterator(list, characteristics());
            }
            return ordered.tryAdvance(action);
          }
        };

    return new LongStreamImpl(this, sortedSpliterator);
  }

  @Override
  public LongStream peek(LongConsumer action) {
    checkNotNull(action);
    throwIfTerminated();

    AbstractLongSpliterator peekSpliterator =
        new Spliterators.AbstractLongSpliterator(
            spliterator.estimateSize(), spliterator.characteristics()) {
          @Override
          public boolean tryAdvance(final LongConsumer innerAction) {
            return spliterator.tryAdvance(action.andThen(innerAction));
          }
        };

    return new LongStreamImpl(this, peekSpliterator);
  }

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

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

  @Override
  public DoubleStream asDoubleStream() {
    return mapToDouble(x -> (double) x);
  }

  @Override
  public Stream<Long> boxed() {
    return mapToObj(Long::valueOf);
  }

  @Override
  public LongStream sequential() {
    throwIfTerminated();
    return this;
  }

  @Override
  public LongStream parallel() {
    throwIfTerminated();
    return this;
  }

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

  @Override
  public LongStream unordered() {
    throwIfTerminated();
    return this;
  }
}
