package net.ranides.assira.collection.iterators;

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

/**
 * Iterator decorator which adds to some "walker" iterator support for removing elements.
 * Effectively it delegates iteration to "walker" and delegates remove to provided "remover".
 *
 * Please note, that remove function must be careful to not invalidate walker iterator.
 * For example, you can create copy of collection and then take "walker" from copy, and remover from original.
 *
 * @param <T> T
 */
public class RemoveIterator<T> implements Iterator<T> {

    private final Iterator<T> walker;
    private final Consumer<T> remover;

    private T last;

    /**
     * Creates composite iterator, which iterates through walker, but delegates remove to "remover"
     *
     * @param walker walker
     * @param remover remover
     */
    public RemoveIterator(Iterator<T> walker, Consumer<T> remover) {
        this.walker = walker;
        this.remover = remover;
        this.last = null;
    }

    @Override
    public boolean hasNext() {
        return walker.hasNext();
    }

    @Override
    public T next() {
        return last = walker.next();
    }

    @Override
    public void remove() {
        if (last == null) {
            throw new IllegalStateException();
        }
        remover.accept(last);
        last = null;
    }

}
