package com.codepoetics.protonpack;
import com.codepoetics.protonpack.comparators.Comparators;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Spliterator;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
class AggregatingSpliterator<I> implements Spliterator<List<I>> {
private final Spliterator<I> source;
private final BiPredicate<List<I>, I> condition;
private boolean wasSameSlide = false;
private List<I> currentSlide = new ArrayList<>();
AggregatingSpliterator(Spliterator<I> source, BiPredicate<List<I>, I> predicate) {
this.source = source;
this.condition = predicate;
}
@Override
public boolean tryAdvance(Consumer<? super List<I>> action) {
boolean hadElements;
do {
hadElements = source.tryAdvance(curElem -> {
wasSameSlide = isSameSlide(curElem);
if(!wasSameSlide) {
action.accept(currentSlide);
currentSlide = new ArrayList<>();
}
currentSlide.add(curElem);
}
);
} while (wasSameSlide && hadElements);
if (!hadElements && !currentSlide.isEmpty()) {
action.accept(currentSlide);
currentSlide = new ArrayList<>();
}
return hadElements;
}
private boolean isSameSlide(I curEl) {
return currentSlide.isEmpty() || condition.test(currentSlide, curEl);
}
@Override
public Spliterator<List<I>> trySplit() {
return null;
}
@Override
public long estimateSize() {
return source.estimateSize();
}
@Override
public int characteristics() {
return source.characteristics() & ~Spliterator.SIZED & ~Spliterator.CONCURRENT;
}
@Override
public Comparator<? super List<I>> getComparator() {
Comparator<? super I> comparator = source.getComparator();
return comparator == null ? null : Comparators.toListComparator(comparator);
}
}