docs: function pluginEventingBehaviour (api) {
      var eventHandlers = {};
  
      var onCustomEvent = function() {
        var args = Array.prototype.slice.call(arguments);
        api.emit(args.shift(), args);
      };
  
      api.on = function (name, callback, context) {
        if (!eventHandlers.hasOwnProperty(name)) {
          eventHandlers[name] = [];
        }
  
        eventHandlers[name].push([callback, context]);
        return api;
      };
  
      api.off = function (name, callback, context) {
        if (!eventHandlers.hasOwnProperty(name) ||
            eventHandlers[name].length === 0) {
          return;
        }
  
        $.filter(eventHandlers[name], function(listener) {
          return listener[0] === callback &&
                  listener[1] === context;
        });
  
        return api;
      };
  
      api.once = function (name, callback, context) {
        var fn = function () {
          api.off(name, fn);
          return callback.apply(context, arguments);
        };
  
        api.on(name, fn);
        return api;
      };
  
      api.emit = function (name, args) {
        $.callAsync(function() {
          if (!eventHandlers.hasOwnProperty(name) && eventHandlers[name].length) {
            return;
          }
  
          $.forEach(eventHandlers[name], function(handler) {
            handler[0].apply(handler[1], args);
          });
        });
  
        return api;
      };
  
      var onReady = function onReady (readyCallback) {
        if (api._.on) {
          // If the plugin supports custom events we'll use them
          api._.on(-1, {
            customEvent: curryCallAsync(onCustomEvent)
          });
        }
  
        // Only the main plugin has an initialise method
        if (api._.initialise) {
          api.on('ready', curryCallAsync(readyCallback));
          api._.initialise();
        }
        else {
          readyCallback.call(api);
        }
      };
  
      return function (completion) {
        onReady(function(err) {
          if (err) {
            OTPlugin.error('Error while starting up plugin ' + api.uuid + ': ' + err);
            completion(err);
            return;
          }
  
          OTPlugin.debug('Plugin ' + api.id + ' is loaded');
          completion(void 0, api);
        });
      };
    }