package brooklyn.util.internal;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;

import org.slf4j.Logger;

public class StreamGobbler extends Thread {
	
    protected final InputStream stream;
    protected final PrintStream out;
    protected final Logger log;
    
    public StreamGobbler(InputStream stream, PrintStream out, Logger log) {
        this.stream = stream;
        this.out = out;
        this.log = log;
    }
    
    String prefix = "";
    public StreamGobbler setPrefix(String prefix) {
		this.prefix = prefix;
		return this;
	}
    
    public void run() {
        int c = -1;
        try {
            while ((c=stream.read())>=0) {
                onChar(c);
            }
            onClose();
        } catch (IOException e) {
        	onClose();
        	//TODO parametrise log level, for this error, and for normal messages
        	if (log!=null) log.debug(prefix+"exception reading from stream ("+e+")");
        }
    }
    
    StringBuffer lineSoFar = new StringBuffer("");
    public void onChar(int c) {
    	if (c=='\n' || c=='\r') {
    		if (lineSoFar.length()>0)
    		    //suppress blank lines, so that we can treat either newline char as a line separator
    		    //(eg to show curl updates frequently)
    		    onLine(lineSoFar.toString());
    		lineSoFar.setLength(0);
    	} else {
    		lineSoFar.append((char)c);
    	}
    }
    
    public void onLine(String line) {
    	//right trim, in case there is \r or other funnies
    	while (line.length()>0 && Character.isWhitespace(line.charAt(line.length()-1)))
    		line = line.substring(0, line.length()-1);
    	//right trim, in case there is \r or other funnies
    	while (line.length()>0 && (line.charAt(0)=='\n' || line.charAt(0)=='\r'))
    		line = line.substring(1);
    	if (out!=null) out.println(prefix+line);
    	if (log!=null && log.isDebugEnabled()) log.debug(prefix+line);
    }
    
    public void onClose() {
    	onLine(lineSoFar.toString());
		lineSoFar.setLength(0);
    }
    
}

@@ -469,25 +469,57 @@
 %0A    String 
-p
+logPrefix = %22%22;%0A    String printP
 refix = %22%22;%0A
@@ -574,34 +574,293 @@
 ) %7B%0A
-%09%09this.prefix = prefix;%0A%09%09
+        setLogPrefix(prefix);%0A        setPrintPrefix(prefix);%0A%09%09return this;%0A%09%7D%0A    public StreamGobbler setPrintPrefix(String prefix) %7B%0A        printPrefix = prefix;%0A        return this;%0A    %7D%0A    public StreamGobbler setLogPrefix(String prefix) %7B%0A        logPrefix = prefix;%0A        
 retu
@@ -864,26 +864,33 @@
 eturn this;%0A
-%09%7D
+    %7D    
 %0A    %0A    pu
@@ -1211,25 +1211,28 @@
 ) log.debug(
-p
+logP
 refix+%22excep
@@ -2116,16 +2116,48 @@
     %09if 
+(!line.isEmpty()) %7B%0A    %09    if 
 (out!=nu
@@ -2174,16 +2174,21 @@
 intln(pr
+intPr
 efix+lin
@@ -2192,24 +2192,28 @@
 line);%0A    %09
+    
 if (log!=nul
@@ -2249,17 +2249,20 @@
 g.debug(
-p
+logP
 refix+li
@@ -2262,24 +2262,31 @@
 efix+line);%0A
+    %09%7D%0A
     %7D%0A    %0A 
@@ -2316,17 +2316,20 @@
 ) %7B%0A    
+  
-%09
+  
 onLine(l
@@ -2350,18 +2350,24 @@
 ing());%0A
-%09%09
+        
 lineSoFa
@@ -2386,17 +2386,442 @@
 0);%0A    
-%7D%0A
     
+finished = true;%0A        synchronized (this) %7B notifyAll(); %7D%0A    %7D%0A    %0A    private volatile boolean finished = false;%0A%0A    /** convenience -- equivalent to calling join() */%0A    public void blockUntilFinished() throws InterruptedException %7B%0A        synchronized (this) %7B while (!finished) wait(); %7D%0A    %7D%0A%0A    /** convenience -- similar to !Thread.isAlive() */%0A    public boolean isFinished() %7B%0A        return finished;%0A    %7D
 %0A%7D%0A

allow different prefix for log and for a supplied printstream