/*
 * 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.checkState;

import java.util.Arrays;
import java.util.Comparator;
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.LongBinaryOperator;
import java.util.function.LongConsumer;
import java.util.function.LongFunction;
import java.util.function.LongPredicate;
import java.util.function.LongSupplier;
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;

/**
 * See <a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/LongStream.html">
 * the official Java API doc</a> for details.
 */
public interface LongStream extends BaseStream<Long, LongStream> {

  /**
   * See <a
   * href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/LongStream.Builder.html">the
   * official Java API doc</a> for details.
   */
  interface Builder extends LongConsumer {
    @Override
    void accept(long t);

    default LongStream.Builder add(long t) {
      accept(t);
      return this;
    }

    LongStream build();
  }

  static Builder builder() {
    return new Builder() {
      private long[] items = new long[0];

      @Override
      public void accept(long t) {
        checkState(items != null, "Builder already built");
        items[items.length] = t;
      }

      @Override
      public LongStream build() {
        checkState(items != null, "Builder already built");
        LongStream stream = Arrays.stream(items);
        items = null;
        return stream;
      }
    };
  }

  static LongStream concat(LongStream a, LongStream b) {
    // This is nearly the same as flatMap, but inlined, wrapped around a single spliterator of
    // these two objects, and without close() called as the stream progresses. Instead, close is
    // invoked as part of the resulting stream's own onClose, so that either can fail without
    // affecting the other, and correctly collecting suppressed exceptions.

    // TODO replace this flatMap-ish spliterator with one that directly combines the two root
    // streams
    Spliterator<? extends LongStream> spliteratorOfStreams = Arrays.asList(a, b).spliterator();

    AbstractLongSpliterator spliterator =
        new Spliterators.AbstractLongSpliterator(Long.MAX_VALUE, 0) {
          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 {
                // 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) {
                      next = n.spliterator();
                    }
                  })) {
                return false;
              }
            }
            return true;
          }
        };

    LongStream result = new LongStreamImpl(null, spliterator);

    return result.onClose(a::close).onClose(b::close);
  }

  static LongStream empty() {
    return new LongStreamImpl.Empty(null);
  }

  static LongStream generate(LongSupplier s) {
    AbstractLongSpliterator spltierator =
        new Spliterators.AbstractLongSpliterator(
            Long.MAX_VALUE, Spliterator.IMMUTABLE | Spliterator.ORDERED) {
          @Override
          public boolean tryAdvance(LongConsumer action) {
            action.accept(s.getAsLong());
            return true;
          }
        };

    return StreamSupport.longStream(spltierator, false);
  }

  static LongStream iterate(long seed, LongUnaryOperator f) {
    AbstractLongSpliterator spliterator =
        new Spliterators.AbstractLongSpliterator(
            Long.MAX_VALUE, Spliterator.IMMUTABLE | Spliterator.ORDERED) {
          private long next = seed;

          @Override
          public boolean tryAdvance(LongConsumer action) {
            action.accept(next);
            next = f.applyAsLong(next);
            return true;
          }
        };
    return StreamSupport.longStream(spliterator, false);
  }

  static LongStream of(long... values) {
    return Arrays.stream(values);
  }

  static LongStream of(long t) {
    // TODO consider a splittable that returns only a single value
    return of(new long[] {t});
  }

  static LongStream range(long startInclusive, long endExclusive) {
    if (startInclusive >= endExclusive) {
      return empty();
    }
    return rangeClosed(startInclusive, endExclusive - 1);
  }

  static LongStream rangeClosed(long startInclusive, long endInclusive) {
    if (startInclusive > endInclusive) {
      return empty();
    }
    long count = endInclusive - startInclusive + 1;

    AbstractLongSpliterator spliterator =
        new Spliterators.AbstractLongSpliterator(
            count,
            Spliterator.IMMUTABLE
                | Spliterator.SIZED
                | Spliterator.SUBSIZED
                | Spliterator.ORDERED
                | Spliterator.SORTED
                | Spliterator.DISTINCT) {
          private long next = startInclusive;

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

          @Override
          public boolean tryAdvance(LongConsumer action) {
            if (next <= endInclusive) {
              action.accept(next++);
              return true;
            }
            return false;
          }
        };

    return StreamSupport.longStream(spliterator, false);
  }

  boolean allMatch(LongPredicate predicate);

  boolean anyMatch(LongPredicate predicate);

  DoubleStream asDoubleStream();

  OptionalDouble average();

  Stream<Long> boxed();

  <R> R collect(Supplier<R> supplier, ObjLongConsumer<R> accumulator, BiConsumer<R, R> combiner);

  long count();

  LongStream distinct();

  LongStream filter(LongPredicate predicate);

  OptionalLong findAny();

  OptionalLong findFirst();

  LongStream flatMap(LongFunction<? extends LongStream> mapper);

  void forEach(LongConsumer action);

  void forEachOrdered(LongConsumer action);

  @Override
  PrimitiveIterator.OfLong iterator();

  LongStream limit(long maxSize);

  LongStream map(LongUnaryOperator mapper);

  DoubleStream mapToDouble(LongToDoubleFunction mapper);

  IntStream mapToInt(LongToIntFunction mapper);

  <U> Stream<U> mapToObj(LongFunction<? extends U> mapper);

  OptionalLong max();

  OptionalLong min();

  boolean noneMatch(LongPredicate predicate);

  @Override
  LongStream parallel();

  LongStream peek(LongConsumer action);

  OptionalLong reduce(LongBinaryOperator op);

  long reduce(long identity, LongBinaryOperator op);

  @Override
  LongStream sequential();

  LongStream skip(long n);

  LongStream sorted();

  @Override
  Spliterator.OfLong spliterator();

  long sum();

  LongSummaryStatistics summaryStatistics();

  long[] toArray();
}
