package lrs.lazyLRSEvaluators;

import lrs.*;
import fp.*;

/**
 * Takes two lists, one list of integers Li(i1, li2, li3,...) and one list
 * of objects Lo(o1, o2,...). It lazily creates a list that contains i1
 * elements of o1, followed by i2 elements of o2, and so on.
 * If one of the two lists Li or Lo ends, this list ends.
 */
public class LazyListNCopiesEval extends ALazyEval {
    /** Constructs a LazyListNCopiesEval, which creates a lazy list.
      * @param li input list with integers
      * @param lo input list with objects
      */
    public LazyListNCopiesEval(LRStruct li, LRStruct lo) {
        this.li = li;
        this.lo = lo;
    }
    
    // FOR STUDENT TO COMPLETE: add fields and methods here
    protected LRStruct li;
    protected LRStruct lo;
    protected LRStruct out = new LRStruct();
    
    public LRStruct nextLRS() {
        return makeLRS();
    }
    
    /**
     * If the lambda list is non-empty, remove the lambda a lambda and pass the value list
     * to it. Return the value of the lambda application. If the lambda list is empty,
     * clone the value list.
     * @return a list with the elements that come out of the lambdas.
     */
    public LRStruct makeLRS() {
        return (LRStruct)out.execute(new IAlgo() {
            public Object emptyCase(LRStruct host, Object... inp) {
                // out list is empty
                return (LRStruct)li.execute(new IAlgo() {
                    public Object emptyCase(LRStruct host, Object... inp) {
                        // returning a non-lazy empty LRStruct will prevent
                        // the code from returning here
                        return new LRStruct(); // empty
                    }
                    public Object nonEmptyCase(final LRStruct ihost, Object... inp) {
                        return (LRStruct)lo.execute(new IAlgo() {
                            public Object emptyCase(LRStruct host, Object... inp) {
                                // returning a non-lazy empty LRStruct will prevent
                                // the code from returning here
                                return new LRStruct(); // empty
                            }
                            public Object nonEmptyCase(LRStruct host, Object... inp) {
                                // both non-empty
                                out = new LazyNCopiesEval(host.removeFront(), (Integer)ihost.removeFront()).makeLRS();
                                return makeLRS();
                            }
                        });
                    }
                });
            }
            public Object nonEmptyCase(LRStruct host, Object... inp) {
                // out list is still non-empty, return first element of it
                return makeLazyLRS(host.removeFront());
            }
        });
    }    
}
