// Generated by IcedCoffeeScript 1.6.3-j
(function() {
  var Engine, List, iced, spawn, util, __iced_k, __iced_k_noop,
    __slice = [].slice;

  iced = require('iced-coffee-script').iced;
  __iced_k = __iced_k_noop = function() {};

  spawn = require('child_process').spawn;

  List = require('iced-data-structures').List;

  util = require('util');

  exports.Engine = Engine = (function() {
    function Engine(_arg) {
      var opts;
      this.args = _arg.args, this.name = _arg.name, opts = _arg.opts;
      this._exit_code = null;
      this._exit_cb = null;
      this._n_out = 0;
      this._opts = opts || {};
      this._probes = new List;
      this._data_buffers = {
        stderr: [],
        stdout: []
      };
      this._started = false;
    }

    Engine.prototype.collect = function(which) {
      var out;
      out = Buffer.concat(this._data_buffers[which]);
      this._data_buffers[which] = [];
      return out;
    };

    Engine.prototype.stdout = function() {
      return this.collect('stdout');
    };

    Engine.prototype.stderr = function() {
      return this.collect('stderr');
    };

    Engine.prototype._got_data = function(data, source) {
      var s, _ref, _ref1, _ref2, _ref3;
      this._data_buffers[source].push(data);
      s = data.toString('utf8');
      if (((_ref = this._opts) != null ? (_ref1 = _ref.debug) != null ? _ref1[source] : void 0 : void 0) != null) {
        console.error("Got data on " + source + " >>>>>");
        console.error(s);
        console.error("<<<<<");
      }
      if (((_ref2 = this._opts) != null ? (_ref3 = _ref2.passthrough) != null ? _ref3[source] : void 0 : void 0) != null) {
        process[source].write(data, 'utf8');
      }
      return this._probes.walk((function(_this) {
        return function(o) {
          var out_data;
          if ((o.source === source) && s.match(o.pattern)) {
            if (!o.repeat) {
              _this._probes.remove(o);
            }
            out_data = _this.collect(source);
            o.cb(null, out_data, source);
            return false;
          } else {
            return true;
          }
        };
      })(this));
    };

    Engine.prototype._clear_probes = function() {
      return this._probes.walk((function(_this) {
        return function(o) {
          _this._probes.remove(o);
          if (!o.repeat) {
            return o.cb(new Error("EOF before expectation met"));
          }
        };
      })(this));
    };

    Engine.prototype.expect = function(_arg, cb) {
      var pattern, repeat, source;
      source = _arg.source, pattern = _arg.pattern, repeat = _arg.repeat;
      this._start_pipes();
      if (source == null) {
        source = 'stdout';
      }
      this._probes.push({
        source: source,
        pattern: pattern,
        repeat: repeat,
        cb: cb
      });
      return this;
    };

    Engine.prototype.run = function() {
      this.proc = spawn(this.name, this.args);
      this.pid = this.proc.pid;
      this._n_out = 3;
      return this;
    };

    Engine.prototype._start_pipes = function() {
      if (this._started) {
        return;
      }
      this._started = true;
      this.proc.on('exit', (function(_this) {
        return function(status) {
          return _this._got_exit(status);
        };
      })(this));
      this.proc.stderr.on('end', (function(_this) {
        return function() {
          return _this._maybe_finish();
        };
      })(this));
      this.proc.stdout.on('end', (function(_this) {
        return function() {
          return _this._maybe_finish();
        };
      })(this));
      this.proc.stderr.on('data', (function(_this) {
        return function(data) {
          return _this._got_data(data, 'stderr');
        };
      })(this));
      return this.proc.stdout.on('data', (function(_this) {
        return function(data) {
          return _this._got_data(data, 'stdout');
        };
      })(this));
    };

    Engine.prototype.sendline = function() {
      var args;
      args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
      if (args[0].slice(-1)[0] !== "\n") {
        args[0] += "\n";
      }
      return this.send.apply(this, args);
    };

    Engine.prototype.send = function() {
      var args, _ref;
      args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
      this._start_pipes();
      if (this.proc) {
        return (_ref = this.proc.stdin).write.apply(_ref, args);
      } else {
        return args.slice(-1)[0](new Error("EOF on input; can't send"));
      }
    };

    Engine.prototype._got_exit = function(status) {
      this._exit_code = status;
      this.proc = null;
      return this._maybe_finish();
    };

    Engine.prototype._maybe_finish = function() {
      var ecb;
      if (--this._n_out <= 0) {
        this._clear_probes();
        if ((ecb = this._exit_cb) != null) {
          this._exit_cb = null;
          ecb(this._exit_code);
        }
        return this.pid = -1;
      }
    };

    Engine.prototype.conversation = function(list, cb) {
      var err, i, item, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      err = null;
      (function(_this) {
        return (function(__iced_k) {
          var _i, _len, _ref, _results, _while;
          _ref = list;
          _len = _ref.length;
          i = 0;
          _results = [];
          _while = function(__iced_k) {
            var _break, _continue, _next;
            _break = function() {
              return __iced_k(_results);
            };
            _continue = function() {
              return iced.trampoline(function() {
                ++i;
                return _while(__iced_k);
              });
            };
            _next = function(__iced_next_arg) {
              _results.push(__iced_next_arg);
              return _continue();
            };
            if (!(i < _len)) {
              return _break();
            } else {
              item = _ref[i];
              (function(__iced_k) {
                __iced_deferrals = new iced.Deferrals(__iced_k, {
                  parent: ___iced_passed_deferral,
                  filename: "/Users/max/src/iced-expect/src/main.iced",
                  funcname: "Engine.conversation"
                });
                _this._do_obj(item, "item " + i, __iced_deferrals.defer({
                  assign_fn: (function() {
                    return function() {
                      return err = arguments[0];
                    };
                  })(),
                  lineno: 122
                }));
                __iced_deferrals._fulfill();
              })(function() {
                (function(__iced_k) {
                  if (err != null) {
                    (function(__iced_k) {
_break()
                    })(__iced_k);
                  } else {
                    return __iced_k();
                  }
                })(_next);
              });
            }
          };
          _while(__iced_k);
        });
      })(this)((function(_this) {
        return function() {
          return cb(err);
        };
      })(this));
    };

    Engine.prototype._do_obj = function(obj, what, cb) {
      var arg, err, k, v, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      err = null;
      (function(_this) {
        return (function(__iced_k) {
          if (typeof obj !== 'object') {
            return __iced_k(err = new Error("" + what + " wasn't a dictionary as expected"));
          } else {
            (function(__iced_k) {
              if (Object.keys(obj).length !== 1) {
                return __iced_k(err = new Error("Expected only one kv-pair per item; got otherwise in " + what));
              } else {
                k = Object.keys(obj)[0];
                v = obj[k];
                (function(__iced_k) {
                  switch (k) {
                    case 'expect':
                      if ((typeof v === 'string') || (typeof v === 'object' && util.isRegExp(v))) {
                        arg = {
                          pattern: v
                        };
                      } else if (typeof v !== 'object') {
                        err = new Error("Bad argument to 'expect' in " + what);
                      } else {
                        arg = v;
                      }
                      (function(__iced_k) {
                        if (err == null) {
                          (function(__iced_k) {
                            __iced_deferrals = new iced.Deferrals(__iced_k, {
                              parent: ___iced_passed_deferral,
                              filename: "/Users/max/src/iced-expect/src/main.iced",
                              funcname: "Engine._do_obj"
                            });
                            _this.expect(arg, __iced_deferrals.defer({
                              assign_fn: (function() {
                                return function() {
                                  return err = arguments[0];
                                };
                              })(),
                              lineno: 146
                            }));
                            __iced_deferrals._fulfill();
                          })(__iced_k);
                        } else {
                          return __iced_k();
                        }
                      })(__iced_k);
                      break;
                    case 'send':
                    case 'sendline':
                      (function(__iced_k) {
                        if (typeof v === 'string') {
                          (function(__iced_k) {
                            __iced_deferrals = new iced.Deferrals(__iced_k, {
                              parent: ___iced_passed_deferral,
                              filename: "/Users/max/src/iced-expect/src/main.iced",
                              funcname: "Engine._do_obj"
                            });
                            _this[k](v, __iced_deferrals.defer({
                              assign_fn: (function() {
                                return function() {
                                  return err = arguments[0];
                                };
                              })(),
                              lineno: 149
                            }));
                            __iced_deferrals._fulfill();
                          })(__iced_k);
                        } else {
                          return __iced_k(err = new Error("Bad argument to " + k + ": need a string in " + what));
                        }
                      })(__iced_k);
                      break;
                    default:
                      return __iced_k(err = new Error("Unknown command: " + k));
                  }
                })(__iced_k);
              }
            })(__iced_k);
          }
        });
      })(this)((function(_this) {
        return function() {
          return cb(err);
        };
      })(this));
    };

    Engine.prototype.wait = function(cb) {
      this._start_pipes();
      if ((this._exit_code != null) && this._n_out <= 0) {
        return cb(this._exit_code);
      } else {
        return this._exit_cb = cb;
      }
    };

    return Engine;

  })();

}).call(this);
