/*
java child_process		: http://www.rgagnon.com/javadetails/java-0014.html
*/

package org.apache.cordova.plugin;

import android.content.Context;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

public class ShellExec extends CordovaPlugin {

	private static final String pluginName = "child_process";
	public static CallbackContext cb_ctx = null;



/*
@Override
    public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
        if ("beep".equals(action)) {
            final long duration = args.getLong(0);
            cordova.getThreadPool().execute(new Runnable() {
                public void run() {
                    ...
                    callbackContext.success(); // Thread-safe.
                }
            });
            return true;
        }
        return false;
    }
*/
/*
						// String[] cmd = {"/bin/sh", "-c", "ls > hello"};
						// Process process = Runtime.getRuntime().exec(cmd, null, new File("/usr/hadoop-0.20.2/"));
						// exec(cmd, envvars, cwd)
*/
/*
						// OutputStream stdin = null;
						// stdin = p.getOutputStream();
						// String stdinData;
						// stdinData = "myparam" + "\n";
						// stdin.write(stdinData.getBytes());
						// stdin.flush();
						// stdin.close();
*/
/*
							if((stderrData = stderrReader.readLine()) != ""){
								json.put("stderr", stderrData + " CHECK \n");
								res = true;
							}
							if((stdoutData = stdoutReader.readLine()) != ""){
								json.put("stdout", stdoutData + " CHECK \n");
								res = true;
							}
*/
/*
							if((stderrData = stderrReader.readLine()) != null){
								json.put("stderr", stderrData + " CHECK \n");
								res = true;
							}
							if((stdoutData = stdoutReader.readLine()) != null){
								json.put("stdout", stdoutData + " CHECK \n");
								res = true;
							}
*/
// reader.nextLine()
/*
while (inReader.ready()) {
                if ((c = inReader.read()) == -1) {
                    inFinished = true;
                } 
                else {
                    System.out.print((char) c);
                }
            }
*/
/*
This code snippets skips the empty line and only prints the ones with content.

    String line = null;
    while ((line = br.readLine()) != null) {
        if (line.trim().equals("")) {
            // empty line
        } else {
            System.out.println(line);
        }
    }
*/
/*
try {
	Thread.sleep(1000);
} catch (InterruptedException e) {
}
*/
/*
p.destroy()
*/


	@Override
	public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
/*
		if(this.cb_ctx == null){
			this.cb_ctx = callbackContext;
		}
*/
		this.cb_ctx = callbackContext;


        if(action.equals("exec")){
			final String argvs = (String) args.get(0);
			Thread thread = new Thread(new Runnable() {
				public void run() {
		            try {
						Process p = Runtime.getRuntime().exec(argvs);
						boolean run = true;
						int exit = 100;
						JSONObject json = new JSONObject();
						BufferedReader stderrReader = new BufferedReader(new InputStreamReader(p.getErrorStream()));
						BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(p.getInputStream()));
						String stderrData = null;
						String stdoutData = null;
						boolean res = false;

						while(run){
							if(stderrReader.ready()){
								stderrData = stderrReader.readLine()
								json.put("stderr", stderrData);
								res = true;
							}
							if(stdoutReader.ready()){
								stdoutData = stdoutReader.readLine()
								json.put("stdout", stdoutData);
								res = true;
							}
							try{
								exit = p.exitValue();
								json.put("exit", exit);
								res = true;
								run = false;
								stderrReader.close();
								stdoutReader.close();
							}catch(IllegalThreadStateException e){
								run = true;
							}
							if(res == true){
								PluginResult result = new PluginResult(PluginResult.Status.OK, json);
								result.setKeepCallback(true);
								cb_ctx.sendPluginResult(result);
								json.remove("stderr");
								json.remove("stdout");
								res = false;
							}

                        }
		            }catch(IOException e){
						// Log.e(pluginName, "Error spawn IOException: " + e.getMessage(), e);
		            }catch(JSONException e){
						// Log.e(pluginName, "Error spawn JSONException: " + e.getMessage(), e);
					}
				}
			});
			thread.start();
			return true;
        }

        if(action.equals("exec2")){
			final String argvs = (String) args.get(0);
			Thread thread = new Thread(new Runnable() {
				public void run() {
		            try {
						Process p = Runtime.getRuntime().exec(argvs);
						boolean run = true;
						int exit = 100;
						JSONObject json = new JSONObject();
						BufferedReader stderrReader = new BufferedReader(new InputStreamReader(p.getErrorStream()));
						BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(p.getInputStream()));
						int stderrData;
						int stdoutData;
						char[] stderrBuffer = new char[4096];
						char[] stdoutBuffer = new char[4096];
						boolean res = false;

						while(run){
							if(stderrReader.ready()){
								stderrData = stderrReader.read(stderrBuffer);
								json.put("stderr", stderrData);
								res = true;
							}
							if(stdoutReader.ready()){
								stdoutData = stdoutReader.read(stdoutBuffer);
								json.put("stdout", stdoutData);
								res = true;
							}


							try{
								exit = p.exitValue();
								json.put("exit", exit);
								res = true;
								run = false;
								stderrReader.close();
								stdoutReader.close();
							}catch(IllegalThreadStateException e){
								run = true;
							}
							if(res == true){
								PluginResult result = new PluginResult(PluginResult.Status.OK, json);
								result.setKeepCallback(true);
								cb_ctx.sendPluginResult(result);
								json.remove("stderr");
								json.remove("stdout");
								res = false;
							}

                        }
		            }catch(IOException e){
						// Log.e(pluginName, "Error spawn IOException: " + e.getMessage(), e);
		            }catch(JSONException e){
						// Log.e(pluginName, "Error spawn JSONException: " + e.getMessage(), e);
					}
				}
			});
			thread.start();
			return true;
        }

        if(action.equals("execSync")){
			int exit = 100;
			StringBuffer stderrStrBuffer = new StringBuffer();
			StringBuffer stdoutStrBuffer = new StringBuffer();
			try {
				Process p = Runtime.getRuntime().exec((String) args.get(0));
				BufferedReader stderrReader = new BufferedReader(new InputStreamReader(p.getErrorStream()));
				BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(p.getInputStream()));
				int stderrData;
				int stdoutData;
				char[] stderrBuffer = new char[4096];
				char[] stdoutBuffer = new char[4096];

				while ((stderrData = stderrReader.read(stderrBuffer)) > 0) {
					stderrStrBuffer.append(stderrBuffer, 0, stderrData);
				}
				stderrReader.close();
				while ((stdoutData = stdoutReader.read(stdoutBuffer)) > 0) {
					stdoutStrBuffer.append(stdoutBuffer, 0, stdoutData);
				}
				stdoutReader.close();

				p.waitFor();
				exit = p.exitValue();
			}catch(IOException e){
				Log.e(pluginName, "Error execSync IOException: " + e.getMessage(), e);
			} catch(InterruptedException e){
				Log.e(pluginName, "Error execSync InterruptedException: " + e.getMessage(), e);
			}
			JSONObject json = new JSONObject();
			json.put("exit", exit);
			json.put("stderr", stderrStrBuffer.toString());
			json.put("stdout", stdoutStrBuffer.toString());
			callbackContext.success(json);
			return true;
        }
        return false;
	}
}
