(function () {

/* Imports */
var Meteor = Package.meteor.Meteor;
var _ = Package.underscore._;

/* Package-scope variables */
var EV;

(function(){

///////////////////////////////////////////////////////////////////////
//                                                                   //
// packages/arunoda_streams/packages/arunoda_streams.js              //
//                                                                   //
///////////////////////////////////////////////////////////////////////
                                                                     //
(function () {                                                       // 1
                                                                     // 2
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                   //
// packages/arunoda:streams/lib/ev.js                                                                                //
//                                                                                                                   //
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                                                                     //
function _EV() {                                                                                                     // 1
  var self = this;                                                                                                   // 2
  var handlers = {};                                                                                                 // 3
                                                                                                                     // 4
  self.emit = function emit(event) {                                                                                 // 5
    var args = Array.prototype.slice.call(arguments, 1);                                                             // 6
                                                                                                                     // 7
    if(handlers[event]) {                                                                                            // 8
      for(var lc=0; lc<handlers[event].length; lc++) {                                                               // 9
        var handler = handlers[event][lc];                                                                           // 10
        handler.apply(this, args);                                                                                   // 11
      }                                                                                                              // 12
    }                                                                                                                // 13
  };                                                                                                                 // 14
                                                                                                                     // 15
  self.on = function on(event, callback) {                                                                           // 16
    if(!handlers[event]) {                                                                                           // 17
      handlers[event] = [];                                                                                          // 18
    }                                                                                                                // 19
    handlers[event].push(callback);                                                                                  // 20
  };                                                                                                                 // 21
                                                                                                                     // 22
  self.once = function once(event, callback) {                                                                       // 23
    self.on(event, function onetimeCallback() {                                                                      // 24
      callback.apply(this, arguments);                                                                               // 25
      self.removeListener(event, onetimeCallback);                                                                   // 26
    });                                                                                                              // 27
  };                                                                                                                 // 28
                                                                                                                     // 29
  self.removeListener = function removeListener(event, callback) {                                                   // 30
    if(handlers[event]) {                                                                                            // 31
      var index = handlers[event].indexOf(callback);                                                                 // 32
      handlers[event].splice(index, 1);                                                                              // 33
    }                                                                                                                // 34
  };                                                                                                                 // 35
                                                                                                                     // 36
  self.removeAllListeners = function removeAllListeners(event) {                                                     // 37
    handlers[event] = undefined;                                                                                     // 38
  };                                                                                                                 // 39
}                                                                                                                    // 40
                                                                                                                     // 41
EV = _EV;                                                                                                            // 42
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                     // 52
}).call(this);                                                       // 53
                                                                     // 54
                                                                     // 55
                                                                     // 56
                                                                     // 57
                                                                     // 58
                                                                     // 59
(function () {                                                       // 60
                                                                     // 61
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                   //
// packages/arunoda:streams/lib/server.js                                                                            //
//                                                                                                                   //
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                                                                     //
var EventEmitter = Npm.require('events').EventEmitter;                                                               // 1
var util = Npm.require('util');                                                                                      // 2
var Fibers = Npm.require('fibers');                                                                                  // 3
                                                                                                                     // 4
Meteor.Stream = function Stream(name) {                                                                              // 5
  EV.call(this);                                                                                                     // 6
                                                                                                                     // 7
  var self = this;                                                                                                   // 8
  var streamName = 'stream-' + name;                                                                                 // 9
  var allowFunction;                                                                                                 // 10
  var allowResultCache = true;                                                                                       // 11
  var allowResults = {};                                                                                             // 12
  var filters = [];                                                                                                  // 13
                                                                                                                     // 14
  self.name = name;                                                                                                  // 15
                                                                                                                     // 16
  var events = new EventEmitter();                                                                                   // 17
  events.setMaxListeners(0);                                                                                         // 18
                                                                                                                     // 19
  var disconnectEvents = new EV();                                                                                   // 20
                                                                                                                     // 21
  self._emit = self.emit;                                                                                            // 22
  self.emit = function emit() {                                                                                      // 23
    self.emitToSubscriptions(arguments, null, null);                                                                 // 24
  };                                                                                                                 // 25
                                                                                                                     // 26
  var defaultResult =  (typeof(Package) == 'object' && Package.insecure)? true: Meteor.Collection.insecure === true; // 27
  self.permissions = new Meteor.Stream.Permission(defaultResult, true);                                              // 28
                                                                                                                     // 29
  self.addFilter = function addFilter(callback) {                                                                    // 30
    filters.push(callback);                                                                                          // 31
  };                                                                                                                 // 32
                                                                                                                     // 33
  self.emitToSubscriptions = function emitToSubscriptions(args, subscriptionId, userId) {                            // 34
    events.emit('item', {args: args, userId: userId, subscriptionId: subscriptionId});                               // 35
  };                                                                                                                 // 36
                                                                                                                     // 37
  Meteor.publish(streamName, function() {                                                                            // 38
    check(arguments, Match.Any);                                                                                     // 39
    var subscriptionId = Random.id();                                                                                // 40
    var publication = this;                                                                                          // 41
                                                                                                                     // 42
    //send subscription id as the first document                                                                     // 43
    publication.added(streamName, subscriptionId, {type: 'subscriptionId'});                                         // 44
    publication.ready();                                                                                             // 45
    events.on('item', onItem);                                                                                       // 46
                                                                                                                     // 47
    function onItem(item) {                                                                                          // 48
      Fibers(function() {                                                                                            // 49
        var id = Random.id();                                                                                        // 50
        if(self.permissions.checkPermission('read', subscriptionId, publication.userId, item.args)) {                // 51
          //do not send again this to the sender                                                                     // 52
          if(subscriptionId != item.subscriptionId) {                                                                // 53
            publication.added(streamName, id, item);                                                                 // 54
            publication.removed(streamName, id);                                                                     // 55
          }                                                                                                          // 56
        }                                                                                                            // 57
      }).run();                                                                                                      // 58
    }                                                                                                                // 59
                                                                                                                     // 60
    publication.onStop(function() {                                                                                  // 61
      //trigger related onDisconnect handlers if exists                                                              // 62
      Fibers(function() {                                                                                            // 63
        disconnectEvents.emit(subscriptionId);                                                                       // 64
        disconnectEvents.removeAllListeners(subscriptionId);                                                         // 65
      }).run();                                                                                                      // 66
      events.removeListener('item', onItem);                                                                         // 67
    });                                                                                                              // 68
  });                                                                                                                // 69
                                                                                                                     // 70
  var methods = {};                                                                                                  // 71
  methods[streamName] = function(subscriptionId, args) {                                                             // 72
    check(arguments, Match.Any);                                                                                     // 73
    //in order to send this to the server callback                                                                   // 74
    var userId = this.userId;                                                                                        // 75
    Fibers(function() {                                                                                              // 76
      var methodContext = {};                                                                                        // 77
      methodContext.userId = userId;                                                                                 // 78
      methodContext.subscriptionId = subscriptionId;                                                                 // 79
                                                                                                                     // 80
      //in order to send this to the serve callback                                                                  // 81
      methodContext.allowed = self.permissions.checkPermission('write', subscriptionId, methodContext.userId, args); // 82
      if(methodContext.allowed) {                                                                                    // 83
        //apply filters                                                                                              // 84
        args = applyFilters(args, methodContext);                                                                    // 85
        self.emitToSubscriptions(args, subscriptionId, methodContext.userId);                                        // 86
        //send to firehose if exists                                                                                 // 87
        if(self.firehose) {                                                                                          // 88
          self.firehose(args, subscriptionId, methodContext.userId);                                                 // 89
        }                                                                                                            // 90
      }                                                                                                              // 91
      //need to send this to server always                                                                           // 92
      self._emit.apply(methodContext, args);                                                                         // 93
                                                                                                                     // 94
      //register onDisconnect handlers if provided                                                                   // 95
      if(typeof(methodContext.onDisconnect) == 'function') {                                                         // 96
        disconnectEvents.on(subscriptionId, methodContext.onDisconnect)                                              // 97
      }                                                                                                              // 98
                                                                                                                     // 99
    }).run();                                                                                                        // 100
  };                                                                                                                 // 101
  Meteor.methods(methods);                                                                                           // 102
                                                                                                                     // 103
  function applyFilters(args, context) {                                                                             // 104
    var eventName = args.shift();                                                                                    // 105
    filters.forEach(function(filter) {                                                                               // 106
      args = filter.call(context, eventName, args);                                                                  // 107
    });                                                                                                              // 108
    args.unshift(eventName);                                                                                         // 109
    return args;                                                                                                     // 110
  }                                                                                                                  // 111
};                                                                                                                   // 112
                                                                                                                     // 113
util.inherits(Meteor.Stream, EV);                                                                                    // 114
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                     // 183
}).call(this);                                                       // 184
                                                                     // 185
                                                                     // 186
                                                                     // 187
                                                                     // 188
                                                                     // 189
                                                                     // 190
(function () {                                                       // 191
                                                                     // 192
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                   //
// packages/arunoda:streams/lib/stream_permission.js                                                                 //
//                                                                                                                   //
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                                                                     //
Meteor.Stream.Permission = function (acceptAll, cacheAll) {                                                          // 1
  var options = {                                                                                                    // 2
    "read": {                                                                                                        // 3
      results: {}                                                                                                    // 4
    },                                                                                                               // 5
    "write": {                                                                                                       // 6
      results: {}                                                                                                    // 7
    }                                                                                                                // 8
  };                                                                                                                 // 9
                                                                                                                     // 10
  this.read = function(func, cache) {                                                                                // 11
    options['read']['func'] = func;                                                                                  // 12
    options['read']['doCache'] = (cache === undefined)? cacheAll: cache;                                             // 13
  };                                                                                                                 // 14
                                                                                                                     // 15
  this.write = function(func, cache) {                                                                               // 16
    options['write']['func'] = func;                                                                                 // 17
    options['write']['doCache'] = (cache === undefined)? cacheAll: cache;                                            // 18
  };                                                                                                                 // 19
                                                                                                                     // 20
  this.checkPermission = function(type, subscriptionId, userId, args) {                                              // 21
    var eventName = args[0];                                                                                         // 22
    var namespace = subscriptionId + '-' + eventName;                                                                // 23
    var result = options[type].results[namespace];                                                                   // 24
                                                                                                                     // 25
    if(result === undefined) {                                                                                       // 26
      var func = options[type].func;                                                                                 // 27
      if(func) {                                                                                                     // 28
        var context = {subscriptionId: subscriptionId, userId: userId};                                              // 29
        result = func.apply(context, args);                                                                          // 30
        if(options[type].doCache) {                                                                                  // 31
          options[type].results[namespace] = result;                                                                 // 32
        }                                                                                                            // 33
        return result;                                                                                               // 34
      } else {                                                                                                       // 35
        return acceptAll;                                                                                            // 36
      }                                                                                                              // 37
    } else {                                                                                                         // 38
      return result;                                                                                                 // 39
    }                                                                                                                // 40
  };                                                                                                                 // 41
}                                                                                                                    // 42
                                                                                                                     // 43
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                     // 243
}).call(this);                                                       // 244
                                                                     // 245
///////////////////////////////////////////////////////////////////////

}).call(this);


/* Exports */
if (typeof Package === 'undefined') Package = {};
Package['arunoda:streams'] = {};

})();

//# sourceMappingURL=arunoda_streams.js.map