/*
 * @author Ranides Atterwim <ranides@gmail.com>
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */
package net.ranides.assira.collection.iterators;

import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public abstract class ForwardIterator<T> implements Iterator<T> {
    
    private boolean ready = false;
    private T last  = null;
    
    protected abstract boolean next(Consumer<? super T> action);

    @Override
    public boolean hasNext() {
        return ready || (ready = next(v -> last = v));
    }
        
    @Override
    public T next() {
        if(ready) {
            ready = false;
            return last;
        }
        if(!next(v -> last = v)) {
            throw new NoSuchElementException();
        }
        return last;
    }
    
    public static <T> Iterator<T> produce(T current, Function<? super T,? extends T> next) {
        return new MIterator<>(current, next);
    }
    
    private static final class MIterator<T> extends ForwardIterator<T> {
        
        private final Function<? super T,? extends T> next;
                
        private T current;

        public MIterator(T current, Function<? super T,? extends T> next) {
            this.next = next;
            this.current = current;
        }
        
        @Override
        protected boolean next(Consumer<? super T> action) {
            if(null == current) {
                return false;
            }
            action.accept(current);
            current = next.apply(current);
            return true;
        }
    }
    
}
