package com.github.aureliano.damihilogs.reader;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.log4j.Logger;

import com.github.aureliano.damihilogs.config.input.ExternalCommandInput;
import com.github.aureliano.damihilogs.exception.DaMihiLogsException;

public class ExternalCommandDataReader extends AbstractDataReader {

	private Process process;
	private BufferedReader bufferedReader;
	private ExternalCommandInput externalCommandInput;
	
	private static final Logger logger = Logger.getLogger(ExternalCommandInput.class);
	
	public ExternalCommandDataReader() {
		super();
	}

	@Override
	public String nextData() {
		this.initialize();
		String line = this.readNextLine();
		
		if (line == null) {
			super.markedToStop = true;
			return null;
		}
		
		String data = null;
		super.executeBeforeReadingMethodListeners();
		
		data = super.prepareLogEvent(line);
		super.executeAfterReadingMethodListeners(data);
		
		return data;
	}

	@Override
	public Map<String, Object> executionLog() {
		return new HashMap<String, Object>();
	}

	@Override
	public void endResources() {
		logger.info(" >>> Flushing and closing stream reader.");
		if (this.bufferedReader == null) {
			return;
		}

		if (this.process.exitValue() != 0) {
			logger.warn("External command exited with no normal exit status.");
			logger.warn(this.readError());
		}
		
		this.process.destroy();
		
		try {
			this.bufferedReader.close();
			this.bufferedReader = null;
		} catch (IOException ex) {
			throw new DaMihiLogsException(ex);
		}
	}

	@Override
	protected String readNextLine() {
		try {
			String line = null;
			if (super.unprocessedLine != null) {
				line = super.unprocessedLine;
				super.unprocessedLine = null;
			} else {
				line = this.bufferedReader.readLine();
				if (line != null) {
					super.lineCounter++;
				}
			}
			
			return line;
		} catch (IOException ex) {
			throw new DaMihiLogsException(ex);
		}
	}
	
	private void initialize() {
		if (this.bufferedReader != null) {
			return;
		}
		
		this.externalCommandInput = (ExternalCommandInput) super.inputConfiguration;
		
		logger.info("Execute command " + this.externalCommandInput.getCommand());
		logger.info("With parameters: " + this.externalCommandInput.getParameters());
		
		List<String> command = this.buildCommand();
		
		try {
			this.process = new ProcessBuilder(command).start();
		} catch (IOException ex) {
			throw new DaMihiLogsException(ex);
		}
		
		InputStreamReader inputStreamReader = new InputStreamReader(this.process.getInputStream());
		this.bufferedReader = new BufferedReader(inputStreamReader);
	}
	
	private List<String> buildCommand() {
		List<String> command = new ArrayList<String>();
		command.add(this.externalCommandInput.getCommand());
		
		for (String parameter : this.externalCommandInput.getParameters()) {
			command.add(parameter);
		}
		
		return command;
	}
	
	private String readError() {
		InputStreamReader inputStreamReader = new InputStreamReader(this.process.getErrorStream());
		BufferedReader reader = new BufferedReader(inputStreamReader);
		
		StringBuilder error = new StringBuilder();
		String line = null;
		
		try {
			while ((line = reader.readLine()) != null) {
				error.append(line).append("\n");
			}
			reader.close();
		} catch (IOException ex) {
			throw new DaMihiLogsException(ex);
		}
		
		error.deleteCharAt(error.length() - 1);
		return error.toString();
	}

	@Override
	public void loadLastExecutionLog(Properties properties) { }
}
@@ -156,66 +156,15 @@
 til.
-ArrayList;%0Aimport java.util.HashMap;%0Aimport java.util.List
+HashMap
 ;%0Aim
@@ -2300,198 +2300,99 @@
 ;%0A%09%09
-logger.info(%22With parameters: %22 + this.externalCommandInput.getParameters());%0A%09%09%0A%09%09List%3CString%3E command = this.buildCommand();%0A%09%09%0A%09%09try %7B%0A%09%09%09this.process = new ProcessBuilder(command).start(
+%0A%09%09try %7B%0A%09%09%09this.process = Runtime.getRuntime().exec(this.externalCommandInput.getCommand()
 );%0A%09
@@ -2630,283 +2630,8 @@
 %7D%0A%09%0A
-%09private List%3CString%3E buildCommand() %7B%0A%09%09List%3CString%3E command = new ArrayList%3CString%3E();%0A%09%09command.add(this.externalCommandInput.getCommand());%0A%09%09%0A%09%09for (String parameter : this.externalCommandInput.getParameters()) %7B%0A%09%09%09command.add(parameter);%0A%09%09%7D%0A%09%09%0A%09%09return command;%0A%09%7D%0A%09%0A
 %09pri

Change external command execution way.