package ch.wlkl.shell;

import java.util.ArrayList;

public class LazyOut<R> extends Top implements Read<R> {
	
	final Env<?, R> env;

	static <T> LazyOut<T> make (Env<?, T> e) {
		return e.out() instanceof Buf ? new LazyOut$Lazy<T>(e) : new LazyOut<T>(e);
	}
	public LazyOut(Env<?, R> e) {
		env = e;
	}

	public boolean isLazy() {
		return false;
	}
	
	public void add(Read<R> r) {
		R line;
		r.open("r");
		while (null != (line = r.read()))
			env.write(line);
		r.close();
	}

	public R read() {
		fail("LazyOut.read()");
		return null;
	}

	public void close() {
		fail("LazyOut.close()");
	}

	public void open(String opt) {
		fail("LazyOut.open()");
	}

	public void reset(Object... args) {
		fail("LazyOut.reset");
	}

}

class LazyOut$Lazy<R> extends LazyOut<R> {

	final ArrayList<Read<R>> reader = new ArrayList<Read<R>>();
	final ArrayList<Integer> outSize = new ArrayList<Integer>();

	private Read<R> envOut = null;
	private Read<R> cur = null;
	int outIx = -1;
	int envOutCur = 0;
	
	LazyOut$Lazy(Env<?, R> e) {
		super(e);
	}
	
	public boolean isLazy() {
		return true;
	}
	public void add(Read<R> r) {
		reader.add(r);
		outSize.add(((Buf<?>) env.out()).adder.size());
	}

	public R read() {
		R line;
		if (cur == null) {
			if (outIx >= reader.size())
				return envOut.read();
			if (envOutCur < outSize.get(outIx) && null != (line = envOut.read())) {
				envOutCur ++ ;
				return line;
			}
			(cur = reader.get(outIx)).open("r");
		}
		if (null != (line = cur.read()))
			return line;
		cur.close();
		cur = null;
		outIx++;
		return read();
	}

	public void close() {
		envOut.close();
		if (cur != null)
			cur.close();
		cur = null;
		env.close();
	}

	public void open(String opt) {
		envOut = (Read<R>) env.out();
		envOut.open("r");
		cur = null;
		outIx = 0;
		envOutCur = 0;
	}
}
	

