var EventEmitter = require('events')
var u            = require('./util')
var Hookable     = require('hoox')

function isFunction (f) {
  return 'function' === typeof f
}

function isString (s) {
  return s && 'string' === typeof s
}

function merge (a, b, mapper) {

  for(var k in b) {
    if(b[k] && 'object' === typeof b[k] && !Buffer.isBuffer(b[k]))
      merge(a[k] = {}, b[k], mapper)
    else
      a[k] = mapper(b[k], k)
  }

  return a
}

function find(ary, test) {
  var v
  for(var i = 0; i < ary.length; i++)
    if(v = test(ary[i], i, ary)) return v
  return v
}

module.exports = function (plugins) {

  function create (opts) {
    //change event emitter to something with more rigorous security?
    var api = new EventEmitter()
    create.plugins.forEach(function (plug) {
      var _api = plug.init.call({createClient: create.createClient}, api, opts)
      if(plug.name) {
        var o = {}; o[plug.name] = _api; _api = o
      }
      api = merge(api, _api, function (v, k) {
        if ('function' === typeof v) {
          v = Hookable(v)
          if (plug.manifest && plug.manifest[k] === 'sync') {
            u.hookOptionalCB(v)
          }
        }
        return v
      })
    })

    return api
  }

  create.plugins = []
  create.manifest = {}
  create.permissions = {}

  create.use = function (plug) {
    if(isFunction(plug))
      return create.plugins.push({init: plug}), create

    if(!plug.init)
      throw new Error('plugins *must* have "init" method')

    if(isString(plug.name))
      if(find(create.plugins, function (_plug) {
        return _plug.name === plug.name
      }))
        throw new Error('plugin named:'+plug.name+' is already loaded')

    var name = plug.name
    if(plug.manifest)
      create.manifest =
        u.merge.manifest(create.manifest, plug.manifest, name)
    if(plug.permissions)
      create.permissions =
        u.merge.permissions(create.permissions, plug.permissions, name)
    create.plugins.push(plug)

    return create
  }

  ;[].concat(plugins).filter(Boolean).forEach(create.use)

  return create
}


@@ -101,16 +101,119 @@
 ('hoox')
+%0Avar camelize     = require('to-camel-case')%0A%0Afunction toCamelCase (n) %7B%0A  return n ? camelize(n) : n%0A%7D
 %0A%0Afuncti
@@ -1011,16 +1011,28 @@
 = %7B%7D; o%5B
+toCamelCase(
 plug.nam
@@ -1032,16 +1032,17 @@
 lug.name
+)
 %5D = _api
@@ -1935,21 +1935,34 @@
 nifest, 
+toCamelCase(
 name)
+)
 %0A    if(
@@ -2072,21 +2072,34 @@
 ssions, 
+toCamelCase(
 name)
+)
 %0A    cre

convert names to camelCase, if they have a - in the module name