var es = require('event-stream')

module.exports = function (obj, raw) {
  obj = obj || {}
  var cbs = {}, count = 1
  var s = es.through(function (data) {
    //write - on incoming call 
    data = data.slice()
    var i = data.pop(), args = data.pop(), name = data.pop()
    //if(~i) then there was no callback.    

    if(name != null) {
      args.push(function () {
        var args = [].slice.call(arguments)
        if(~i) s.emit('data', [args, i]) //responses don't have a name.
      })
      try {
        obj[name].apply(obj, args)
      } catch (err) {
        if(~i) s.emit('data', [[err], i])
      }
    } else if(!cbs[i]) {
      //this is some kind of error.
      //either end is mixed up,
      //or the called twice.
      //log this error, but don't throw.
      //this process shouldn't crash because that one did wrong

      return console.error('ERROR: unknown callback id: '+i, data)
    } else {
      cbs[i].apply(null, args)
      delete cbs[i] //no longer need this
    }
  })

  var rpc = s.rpc = function (name, args, cb) {
    if(cb) cbs[++count] = cb
    if(count == 9007199254740992) count = 0 //reset if max
    //that is 900 million million. 
    //if you reach that, dm me, 
    //i'll buy you a beer. @dominictarr
    s.emit('data', [name, args, cb ? count : -1])
  }

  function keys (obj) {
    var keys = []
    for(var k in obj) keys.push(k)
    return keys
  }

  s.wrap = function (remote) {
    var w = {}
    ;(Array.isArray(remote)     ? remote
    : 'string' == typeof remote ? [remote]
    : remote = keys(remote)
    ).forEach(function (k) {
      w[k] = function () {
        var args = [].slice.call(arguments)
        if('function' == typeof args[args.length - 1])
          cb = args.pop()
        rpc(k, args, cb)
      }
    })
    return w
  }
  if(raw)
    return s
  var parse = es.parse()
  //if not 'raw', wrap the string to return
  var duplex = es.duplex(parse
              , parse.pipe(s).pipe(es.stringify()))
  duplex.wrap = s.wrap
  duplex.rpc = s.rpc
  return duplex
}

@@ -110,16 +110,173 @@
 unt = 1%0A
+  function flattenError(err) %7B%0A    if(err instanceof Error)%0A      for(var k in err)%0A        err%5Bk%5D = err%5Bk%5D //flatten so err stringifies %0A    return err%0A  %7D%0A
   var s 
@@ -302,24 +302,24 @@
 on (data) %7B%0A
-
     //write 
@@ -558,32 +558,62 @@
 call(arguments)%0A
+        flattenError(args%5B0%5D)%0A
         if(~i) s
@@ -743,24 +743,68 @@
 ch (err) %7B%0A 
+       console.error(err ? err.stack : err)%0A
        if(~i
@@ -822,19 +822,33 @@
 ata', %5B%5B
+flattenError(
 err
+)
 %5D, i%5D)%0A 

flatten errors so that they stringify properly