package jetbrains.mps.internal.collections.runtime;

/*Generated by MPS */

import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.stream.Stream;
import java.util.ListIterator;

/**
 * Adaptation of stream for lists, allows both to consume lazily the stream and to reuse its result.
 * 
 * @param <T> content
 */
public class StreamSequence<T> extends AbstractSequence<T> {
  private final List<T> cache = new ArrayList<>();
  private final Iterator<T> streamIterator;

  public StreamSequence(Stream<T> stream) {
    this.streamIterator = stream.iterator();
  }

  public class StreamRepeatableIterator implements Iterator<T> {
    public ListIterator<T> listIterator;
    public StreamRepeatableIterator() {
      listIterator = cache.listIterator();
    }

    @Override
    public boolean hasNext() {
      return listIterator.hasNext() || streamIterator.hasNext();
    }
    @Override
    public T next() {
      // Insert into cache if no more items in it
      if (listIterator.hasNext()) {
        return listIterator.next();
      } else {
        T next = streamIterator.next();
        listIterator.add(next);
        return next;
      }
    }
  }

  @Override
  public Iterator<T> iterator() {
    return new StreamRepeatableIterator();
  }
}
