/*
 * Copyright (c) 2009 JSCAPE
 * 1147 S. 53rd Pl., Mesa, Arizona, 85206, U.S.A.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * JSCAPE. ("Confidential Information").  You shall not disclose such
 * Confidential Information and shall use it only in accordance with
 * the terms of the license agreement you entered into with JSCAPE.
 *
 */

package com.jscape.util.collections;

import com.jscape.util.functor.UnaryFunction;

import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;

/**
 * @author Alex Usun
 */
public class TransformIterator<A, R>
        implements Iterator<R> {

    /**
     * Base.
     */
    private final Iterator<? extends A> base;
    /**
     * Function.
     */
    private final UnaryFunction<? super A, ? extends R> function;

    /**
     * @param base     base
     * @param function function
     * @param <A>      <A>
     * @param <R>      <R>
     *
     * @return TransformIterator<A, R>
     */
    public static <A, R> Iterator<R> adapt(Iterator<? extends A> base, UnaryFunction<? super A, ? extends R> function) {
        return new TransformIterator<A, R>(base, function);
    }

    /**
     * @param base     base
     * @param function function
     * @param <A>      <A>
     * @param <R>      <R>
     *
     * @return adapt
     */
    public static <A, R> Iterator<R> iterator(Collection<? extends A> base, UnaryFunction<? super A, ? extends R> function) {
        return adapt(base.iterator(), function);
    }

    /**
     * @param base     base
     * @param function function
     * @param <A>      <A>
     * @param <R>      <R>
     *
     * @return adapt
     */
    public static <A, R> Iterator<R> iterator(Enumeration<A> base, UnaryFunction<? super A, ? extends R> function) {
        return adapt(EnumerationIterator.iterator(base), function);
    }

    /**
     * @param base     base
     * @param function function
     * @param <A>      <A>
     * @param <R>      <R>
     *
     * @return adapt
     */
    public static <A, R> Iterator<R> iterator(A[] base, UnaryFunction<? super A, ? extends R> function) {
        return adapt(ArrayIterator.iterator(base), function);
    }

    /**
     * @param base     base
     * @param function function
     */
    public TransformIterator(Iterator<? extends A> base, UnaryFunction<? super A, ? extends R> function) {
        this.base = base;
        this.function = function;
    }

    /**
     * @return base has next
     */
    public boolean hasNext() {
        return this.base.hasNext();
    }

    /**
     * @return R
     */
    public R next() {
        return this.function.evaluate(this.base.next());
    }

    /** */
    public void remove() {
        this.base.remove();
    }

}