package org.cobbzilla.util.io.multi;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class MultiStream extends InputStream {

    private final List<InputStream> streams = new ArrayList<>();
    private InputStream currentStream;
    private int streamIndex = 0;
    private boolean endOfStreams = false;

    public MultiStream (InputStream r, boolean last) {
        if (last) {
            addLastStream(r);
        } else {
            addStream(r);
        }
        currentStream = r;
    }

    public MultiStream (InputStream r) { this(r, false); }

    public void addStream (InputStream in) {
        if (endOfStreams) {
            log.warn("addStream: endOfStreams is true, not adding InputStream");
        } else {
            streams.add(in);
        }
    }

    public void addLastStream (InputStream in) {
        addStream(in);
        endOfStreams = true;
    }

    @Override public int read() throws IOException {
        final int val = currentStream.read();
        if (val == -1) {
            if (streamIndex == streams.size()-1) {
                return endOfStreams ? -1 : 0;
            }
            currentStream.close();
            streamIndex++;
            currentStream = streams.get(streamIndex);
            return read();
        }
        return val;
    }

    @Override public int read(byte[] buf, int off, int len) throws IOException {
        final int count = currentStream.read(buf, off, len);
        if (count == -1) {
            if (streamIndex == streams.size()-1) {
                return endOfStreams ? -1 : 0;
            }
            currentStream.close();
            streamIndex++;
            currentStream = streams.get(streamIndex);
            return read(buf, off, len);
        }
        return count;
    }

    @Override public void close() throws IOException {
        if (currentStream != null) currentStream.close();
    }

}

@@ -616,373 +616,857 @@
 lic 
-MultiStream (InputStream r) %7B this(r, false); %7D%0A%0A    public void addStream (InputStream in) %7B%0A        if (endOfStreams) %7B%0A            log.warn(%22addStream: endOfStreams is true, not adding InputStream%22);%0A        %7D else %7B%0A            streams.add(in);%0A        %7D%0A    %7D%0A%0A    public void addLastStream (InputStream in) %7B%0A        addStream(in);%0A        endOfStreams = true
+int pendingStreamCount () %7B return streams.size() - streamIndex; %7D%0A%0A    public MultiStream (InputStream r) %7B this(r, false); %7D%0A%0A    @Override public String toString () %7B%0A        return %22MultiStream%7B%22+streams.size()+%22 streams, index=%22+streamIndex+%22, EOS=%22+endOfStreams+%22%7D%22;%0A    %7D%0A%0A    public void addStream (InputStream in) %7B%0A        if (endOfStreams) %7B%0A            log.warn(%22addStream: endOfStreams is true, not adding InputStream%22);%0A        %7D else %7B%0A            streams.add(in);%0A            if (log.isTraceEnabled()) log.trace(%22addStream: added stream (%22+in.getClass().getSimpleName()+%22). this=%22+this);%0A        %7D%0A    %7D%0A%0A    public void addLastStream (InputStream in) %7B%0A        addStream(in);%0A        endOfStreams = true;%0A        if (log.isTraceEnabled()) log.trace(%22addLastStream: added last stream (%22+in.getClass().getSimpleName()+%22). this=%22+this)
 ;%0A  
@@ -1637,32 +1637,131 @@
 ams.size()-1) %7B%0A
+                if (log.isTraceEnabled()) log.trace(%22read(byte): end of all streams? this=%22+this);%0A
                 
@@ -1932,28 +1932,302 @@
         
-return read(
+if (log.isTraceEnabled()) log.trace(%22read(byte): end of all stream, advanced to next stream (%22+currentStream.getClass().getSimpleName()+%22). this=%22+this);%0A            return read();%0A%0A        %7D else %7B%0A            if (log.isTraceEnabled()) log.trace(%22read(byte): one byte read. this=%22+this
 );%0A     
@@ -2470,32 +2470,133 @@
 ams.size()-1) %7B%0A
+                if (log.isTraceEnabled()) log.trace(%22read(byte%5B%5D): end of all streams? this=%22+this);%0A
                 
@@ -2771,129 +2771,586 @@
     
-return read(buf, off, len);%0A        %7D%0A        return count;%0A    %7D%0A%0A    @Override public void close() throws IOException %7B
+if (log.isTraceEnabled()) log.trace(%22read(byte%5B%5D): end of all stream, advanced to next stream (%22+currentStream.getClass().getSimpleName()+%22). this=%22+this);%0A            return read(buf, off, len);%0A%0A        %7D else %7B%0A            if (log.isTraceEnabled()) log.trace(%22read(byte%5B%5D): %22+count+%22 bytes read. this=%22+this);%0A        %7D%0A        return count;%0A    %7D%0A%0A    @Override public void close() throws IOException %7B%0A        if (log.isTraceEnabled()) log.trace(%22close: closing current stream (%22+(currentStream == null ? %22null%22 : currentStream.getClass().getSimpleName())+%22). this=%22+this);
 %0A   

add trace logging