var
  cp = require("child_process"),
  merge = require("merge");

var
  sh, cmd,
  defSpawnOptions = { stdio: "inherit" };

/**
 * @summary Get shell program meta for current platform
 * @private
 * @returns {Object}
 */
function getShell(){
  if (process.platform === "win32") {
    return { cmd: "cmd", arg: "/C" };
  } else {
    return { cmd: "sh", arg: "-c" };
  }
}

/**
 * Callback is called with the output when the process terminates. Output is
 * available when true is passed as options argument or stdio: null set
 * within given options.
 *
 * @summary Execute shell command forwarding all stdio
 * @param {String|Array} command
 * @param {Object|TRUE} [options] spawn() options or TRUE to set stdio: null
 * @param {Function} [callback]
 * @returns {ChildProcess}
 */
function execSh(command, options, callback){
  if (Array.isArray(command)) {
    command = command.join(";");
  }

  if (options === true) {
    options = { stdio: null };
  }

  if (typeof options === "function") {
    callback = options;
    options = defSpawnOptions;
  } else {
    options = options || {};
    options = merge(true, defSpawnOptions, options);
    callback = callback || function(){};
  }

  var
    child,
    stdout = "", stderr = "",
    shell = getShell();

  try {
    child = cp.spawn(shell.cmd, [shell.arg, command], options);
  } catch (e) {
    callback(e, stdout, stderr);
    return;
  }

  if (child.stdout) {
    child.stdout.on("data", function(data){
      stdout += data;
    });
  }

  if (child.stderr) {
    child.stderr.on("data", function(data){
      stderr += data;
    });
  }

  child.on("close", function(code){
    if (code) {
      var e = new Error("Shell command exit with non zero code: " + code);
      e.code = code;
      callback(e, stdout, stderr);
    } else {
      callback(null, stdout, stderr);
    }
  });

  return child;
}

module.exports = execSh;

