// Generated by IcedCoffeeScript 1.7.1-e
(function() {
  var BaseEngine, ExecEngine, SpawnEngine, bufferify, dos_cmd_escape, dos_flatten_argv, exec, fs, iced, run, semver, set_log, spawn, stream, util, __iced_k, __iced_k_noop, _engine, _log, _quiet, _ref,
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    __slice = [].slice;

  iced = require('iced-runtime');
  __iced_k = __iced_k_noop = function() {};

  _ref = require('child_process'), exec = _ref.exec, spawn = _ref.spawn;

  stream = require('./stream');

  util = require('util');

  semver = require('semver');

  fs = require('fs');

  _log = function(x) {
    return process.stderr.write(x.toString('utf8'));
  };

  _engine = null;

  exports.set_log = set_log = function(log) {
    return _log = log;
  };

  exports.set_default_engine = function(e) {
    return _engine = e;
  };

  _quiet = null;

  exports.set_default_quiet = function(q) {
    return _quiet = q;
  };

  BaseEngine = (function() {
    function BaseEngine(_arg) {
      this.args = _arg.args, this.stdin = _arg.stdin, this.stdout = _arg.stdout, this.stderr = _arg.stderr, this.name = _arg.name, this.opts = _arg.opts, this.log = _arg.log;
      this.stderr || (this.stderr = new stream.FnOutStream(this.log || _log));
      this.stdin || (this.stdin = new stream.NullInStream());
      this.stdout || (this.stdout = new stream.NullOutStream());
      this.opts || (this.opts = {});
      this.args || (this.args = []);
      this._exit_cb = null;
    }

    BaseEngine.prototype._maybe_call_callback = function() {
      var cb;
      if ((this._exit_cb != null) && this._can_finish()) {
        cb = this._exit_cb;
        this._exit_cb = null;
        return cb(this._err, this._exit_code);
      }
    };

    BaseEngine.prototype.wait = function(cb) {
      this._exit_cb = cb;
      return this._maybe_call_callback();
    };

    return BaseEngine;

  })();

  dos_cmd_escape = function(cmd) {
    var c, out;
    out = (function() {
      var _i, _len, _results;
      _results = [];
      for (_i = 0, _len = cmd.length; _i < _len; _i++) {
        c = cmd[_i];
        c = "" + c;
        if (c.match(/[&<>()@^| ]/)) {
          _results.push("^" + c);
        } else {
          _results.push(c);
        }
      }
      return _results;
    })();
    return out.join('');
  };

  dos_flatten_argv = function(argv) {
    var a;
    return ((function() {
      var _i, _len, _results;
      _results = [];
      for (_i = 0, _len = argv.length; _i < _len; _i++) {
        a = argv[_i];
        _results.push(dos_cmd_escape(a));
      }
      return _results;
    })()).join(' ');
  };

  exports.SpawnEngine = SpawnEngine = (function(_super) {
    __extends(SpawnEngine, _super);

    function SpawnEngine(_arg) {
      var args, log, name, opts, stderr, stdin, stdout;
      args = _arg.args, stdin = _arg.stdin, stdout = _arg.stdout, stderr = _arg.stderr, name = _arg.name, opts = _arg.opts, log = _arg.log, this.other_fds = _arg.other_fds;
      SpawnEngine.__super__.constructor.call(this, {
        args: args,
        stdin: stdin,
        stdout: stdout,
        stderr: stderr,
        name: name,
        opts: opts,
        log: log
      });
      this._exit_code = null;
      this._err = null;
      this._win32 = process.platform === 'win32';
      this._closed = false;
      this._configure_other_fds();
    }

    SpawnEngine.prototype._configure_other_fds = function() {
      var i, k, max, pipes, v, _i, _ref1;
      if (this.other_fds != null) {
        max = 0;
        _ref1 = this.other_fds;
        for (k in _ref1) {
          v = _ref1[k];
          if (k > max) {
            max = k;
          }
        }
        pipes = (function() {
          var _i, _results;
          _results = [];
          for (_i = 0; _i <= 2; _i++) {
            _results.push('pipe');
          }
          return _results;
        })();
        for (i = _i = 3; 3 <= max ? _i <= max : _i >= max; i = 3 <= max ? ++_i : --_i) {
          pipes.push((this.other_fds[i] ? 'pipe' : null));
        }
        return this.opts.stdio = pipes;
      }
    };

    SpawnEngine.prototype._spawn = function() {
      var args, cmdline, name, opts;
      args = this.args;
      name = this.name;
      opts = this.opts;
      if (this._win32) {
        cmdline = dos_flatten_argv([name].concat(args));
        args = ["/s", "/c", '"' + cmdline + '"'];
        name = "cmd.exe";
        opts = util._extend({}, this.opts);
        opts.windowsVerbatimArguments = true;
      }
      return this.proc = spawn(name, args, opts);
    };

    SpawnEngine.prototype._node_v0_10_workarounds = function(cb) {
      var err, fd, stat, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      (function(_this) {
        return (function(__iced_k) {
          if (true) {
            (function(__iced_k) {
              __iced_deferrals = new iced.Deferrals(__iced_k, {
                parent: ___iced_passed_deferral,
                filename: "/home/max/src/iced/iced-spawn/src/cmd.iced",
                funcname: "SpawnEngine._node_v0_10_workarounds"
              });
              fs.fstat(0, __iced_deferrals.defer({
                assign_fn: (function() {
                  return function() {
                    err = arguments[0];
                    return stat = arguments[1];
                  };
                })(),
                lineno: 105
              }));
              __iced_deferrals._fulfill();
            })(function() {
              (function(__iced_k) {
                if (typeof err !== "undefined" && err !== null) {
                  (function(__iced_k) {
                    __iced_deferrals = new iced.Deferrals(__iced_k, {
                      parent: ___iced_passed_deferral,
                      filename: "/home/max/src/iced/iced-spawn/src/cmd.iced",
                      funcname: "SpawnEngine._node_v0_10_workarounds"
                    });
                    fs.open(process.execPath, "r", __iced_deferrals.defer({
                      assign_fn: (function() {
                        return function() {
                          err = arguments[0];
                          return fd = arguments[1];
                        };
                      })(),
                      lineno: 107
                    }));
                    __iced_deferrals._fulfill();
                  })(function() {
                    return __iced_k(typeof err !== "undefined" && err !== null ? console.error("Workaround for stdin bug failed: " + err.message) : void 0);
                  });
                } else {
                  return __iced_k();
                }
              })(__iced_k);
            });
          } else {
            return __iced_k();
          }
        });
      })(this)((function(_this) {
        return function() {
          return cb();
        };
      })(this));
    };

    SpawnEngine.prototype._node_workarounds = function(cb) {
      var ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      (function(_this) {
        return (function(__iced_k) {
          if (semver.lt(process.version, "v0.11.0")) {
            (function(__iced_k) {
              __iced_deferrals = new iced.Deferrals(__iced_k, {
                parent: ___iced_passed_deferral,
                filename: "/home/max/src/iced/iced-spawn/src/cmd.iced",
                funcname: "SpawnEngine._node_workarounds"
              });
              _this._node_v0_10_workarounds(__iced_deferrals.defer({
                lineno: 119
              }));
              __iced_deferrals._fulfill();
            })(__iced_k);
          } else {
            return __iced_k();
          }
        });
      })(this)((function(_this) {
        return function() {
          return cb();
        };
      })(this));
    };

    SpawnEngine.prototype.run = function(cb) {
      if (cb == null) {
        cb = null;
      }
      this._run(cb);
      return this;
    };

    SpawnEngine.prototype._run = function(cb) {
      var k, v, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/home/max/src/iced/iced-spawn/src/cmd.iced",
            funcname: "SpawnEngine._run"
          });
          _this._node_workarounds(__iced_deferrals.defer({
            lineno: 133
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          var _ref1;
          _this._spawn();
          _this.stdin.pipe(_this.proc.stdin);
          _this.proc.stdout.pipe(_this.stdout);
          _this.proc.stderr.pipe(_this.stderr);
          if (_this.other_fds != null) {
            _ref1 = _this.other_fds;
            for (k in _ref1) {
              v = _ref1[k];
              if (v.is_readable()) {
                v.pipe(_this.proc.stdio[k]);
              } else {
                _this.proc.stdio[k].pipe(v);
              }
            }
          }
          _this.pid = _this.proc.pid;
          _this.proc.on('exit', function(status) {
            return _this._got_exit(status);
          });
          _this.proc.on('error', function(err) {
            return _this._got_error(err);
          });
          _this.proc.on('close', function(code) {
            return _this._got_close(code);
          });
          return typeof cb === "function" ? cb(null) : void 0;
        };
      })(this));
    };

    SpawnEngine.prototype._got_close = function(code) {
      this._closed = true;
      return this._maybe_call_callback();
    };

    SpawnEngine.prototype._got_exit = function(status) {
      this._exit_code = status;
      this.proc = null;
      this.pid = -1;
      return this._maybe_call_callback();
    };

    SpawnEngine.prototype._got_error = function(err) {
      this._err = err;
      this.proc = null;
      this.pid = -1;
      return this._maybe_call_callback();
    };

    SpawnEngine.prototype._can_finish = function() {
      return ((this._err != null) || (this._exit_code != null)) && this._closed;
    };

    return SpawnEngine;

  })(BaseEngine);

  exports.ExecEngine = ExecEngine = (function(_super) {
    __extends(ExecEngine, _super);

    function ExecEngine(_arg) {
      var args, log, name, opts, stderr, stdin, stdout;
      args = _arg.args, stdin = _arg.stdin, stdout = _arg.stdout, stderr = _arg.stderr, name = _arg.name, opts = _arg.opts, log = _arg.log;
      ExecEngine.__super__.constructor.call(this, {
        args: args,
        stdin: stdin,
        stdout: stdout,
        stderr: stderr,
        name: name,
        opts: opts
      });
      this._exec_called_back = false;
    }

    ExecEngine.prototype.run = function() {
      var argv;
      argv = [this.name].concat(this.args).join(" ");
      this.proc = exec(argv, this.opts, (function(_this) {
        return function() {
          var args;
          args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
          return _this._got_exec_cb.apply(_this, args);
        };
      })(this));
      this.stdin.pipe(this.proc.stdin);
      return this;
    };

    ExecEngine.prototype._got_exec_cb = function(err, stdout, stderr) {
      var ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/home/max/src/iced/iced-spawn/src/cmd.iced",
            funcname: "ExecEngine._got_exec_cb"
          });
          _this.stdout.write(stdout, __iced_deferrals.defer({
            lineno: 199
          }));
          _this.stderr.write(stderr, __iced_deferrals.defer({
            lineno: 200
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          _this._err = err;
          if (_this._err == null) {
            _this._exit_code = 0;
          } else if (_this._err != null) {
            if (_this._err.code === 127) {
              _this._err.errno = 'ENOENT';
            } else {
              _this._exit_code = _this._err.code;
              _this._err = null;
            }
          }
          _this._exec_called_back = true;
          return _this._maybe_call_callback();
        };
      })(this));
    };

    ExecEngine.prototype._can_finish = function() {
      return this._exec_called_back;
    };

    return ExecEngine;

  })(BaseEngine);

  exports.Engine = SpawnEngine;

  exports.bufferify = bufferify = function(x) {
    if (x == null) {
      return null;
    } else if (typeof x === 'string') {
      return new Buffer(x, 'utf8');
    } else if (Buffer.isBuffer(x)) {
      return x;
    } else {
      return null;
    }
  };

  exports.run = run = function(inargs, cb) {
    var args, b, def_out, eklass, eng, engklass, err, log, name, opts, other_fds, out, quiet, rc, stderr, stdin, stdout, ___iced_passed_deferral, __iced_deferrals, __iced_k;
    __iced_k = __iced_k_noop;
    ___iced_passed_deferral = iced.findDeferral(arguments);
    args = inargs.args, stdin = inargs.stdin, stdout = inargs.stdout, stderr = inargs.stderr, quiet = inargs.quiet, name = inargs.name, eklass = inargs.eklass, opts = inargs.opts, engklass = inargs.engklass, log = inargs.log, other_fds = inargs.other_fds;
    if ((b = bufferify(stdin)) != null) {
      stdin = new stream.BufferInStream(b);
    }
    if ((quiet || ((_quiet != null) && _quiet)) && (stderr == null)) {
      stderr = new stream.NullOutStream();
    }
    if (stdout == null) {
      def_out = true;
      stdout = new stream.BufferOutStream();
    } else {
      def_out = false;
    }
    err = null;
    engklass || (engklass = _engine || SpawnEngine);
    eng = new engklass({
      args: args,
      stdin: stdin,
      stdout: stdout,
      stderr: stderr,
      name: name,
      opts: opts,
      log: log,
      other_fds: other_fds
    });
    eng.run();
    (function(_this) {
      return (function(__iced_k) {
        __iced_deferrals = new iced.Deferrals(__iced_k, {
          parent: ___iced_passed_deferral,
          filename: "/home/max/src/iced/iced-spawn/src/cmd.iced"
        });
        eng.wait(__iced_deferrals.defer({
          assign_fn: (function() {
            return function() {
              err = arguments[0];
              return rc = arguments[1];
            };
          })(),
          lineno: 250
        }));
        __iced_deferrals._fulfill();
      });
    })(this)((function(_this) {
      return function() {
        if ((err == null) && (rc !== 0)) {
          eklass || (eklass = Error);
          err = new eklass("exit code " + rc);
          err.rc = rc;
        }
        out = def_out ? stdout.data() : null;
        return cb(err, out);
      };
    })(this));
  };

}).call(this);
