/*******************************************************************************
 * Copyright (c) 2010 Robert "Unlogic" Olofsson (unlogic@unlogic.se).
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser Public License v3
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-3.0-standalone.html
 ******************************************************************************/
package se.unlogic.standardutils.exec;

import se.unlogic.standardutils.readwrite.ReadWriteUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;



/**
 * A simple buffered {@link StreamHandler} implementation that prints the input from the {@link InputStream} to the given {@link OutputStream}. If no {@link OutputStream} is given it defaults to System.out.<p>
 * 
 * This implementation inputStream based on the {@link PrintWriter}, {@link InputStreamReader} and {@link BufferedReader} classes.
 * 
 * @author Robert "Unlogic" Olofsson (unlogic@unlogic.se)
 *
 */
public class StreamPrinter extends Thread implements StreamHandler {

   private InputStream inputStream;
   private String prefix;
   private OutputStream outputStream;

   private boolean terminated = false;

   public StreamPrinter(String prefix, OutputStream os) {
      super();
      this.outputStream = os;
      this.prefix = prefix;
   }

   public StreamPrinter(OutputStream os) {
      super();
      this.outputStream = os;
   }

   public StreamPrinter() {}

   public boolean isTerminated(){

      return terminated;
   }

   public void terminate(){

      this.terminated = true;
   }

   @Override
   public void run() {

      InputStreamReader inputStreamReader = null;
      BufferedReader bufferedReader = null;

      try {
         PrintWriter pw = null;

         if (outputStream != null) {
            pw = new PrintWriter(outputStream);
         }else{
            //CHECKSTYLE.OFF: RegexpSinglelineJava
            pw = new PrintWriter(System.out);
            //CHECKSTYLE.ON: RegexpSinglelineJava
         }

         inputStreamReader = new InputStreamReader(inputStream);
         bufferedReader = new BufferedReader(inputStreamReader);

         String line = null;

         if(prefix != null){

            while (!terminated && (line = bufferedReader.readLine()) != null) {

               pw.println(prefix + line);
            }

         }else{

            while (!terminated && (line = bufferedReader.readLine()) != null) {

               pw.println(line);
            }
         }

         if (pw != null) {
            pw.flush();
         }

      } catch (IOException e) {

         throw new RuntimeException(e);

      }finally{
         ReadWriteUtils.closeReader(bufferedReader);
         ReadWriteUtils.closeReader(inputStreamReader);

         this.terminated = true;
      }
   }

   public void handleStream(InputStream is) {
      this.inputStream = is;
      this.start();
   }

   public String getPrefix() {
      return prefix;
   }

   public OutputStream getOutputStream() {
      return outputStream;
   }

   public boolean isFinished() {

      return !this.isAlive();
   }

   public void awaitFinish() {

      try {
         this.join();

      } catch (InterruptedException e) {

         throw new RuntimeException(e);
      }
   }
}
