'use strict';
var util = require('util');
var define = require('define-property');
var CacheBase = require('cache-base');
var Emitter = require('component-emitter');
var isObject = require('isobject');
var merge = require('mixin-deep');
var pascal = require('pascalcase');
var cu = require('class-utils');
function namespace(name) {
var Cache = name ? CacheBase.namespace(name) : CacheBase;
var fns = [];
function Base(config, options) {
if (!(this instanceof Base)) {
return new Base(config, options);
}
Cache.call(this, config);
this.is('base');
this.initBase(config, options);
}
util.inherits(Base, Cache);
Emitter(Base);
Base.prototype.initBase = function(config, options) {
this.options = merge({}, this.options, options);
this.cache = this.cache || {};
this.define('registered', {});
if (name) this[name] = {};
this.define('_callbacks', this._callbacks);
if (isObject(config)) {
this.visit('set', config);
}
Base.run(this, 'use', fns);
};
Base.prototype.is = function(name) {
if (typeof name !== 'string') {
throw new TypeError('expected name to be a string');
}
this.define('is' + pascal(name), true);
this.define('_name', name);
this.define('_appname', name);
return this;
};
Base.prototype.isRegistered = function(name, register) {
if (this.registered.hasOwnProperty(name)) {
return true;
}
if (register !== false) {
this.registered[name] = true;
this.emit('plugin', name);
}
return false;
};
Base.prototype.use = function(fn) {
fn.call(this, this);
return this;
};
Base.prototype.define = function(key, val) {
if (isObject(key)) {
return this.visit('define', key);
}
define(this, key, val);
return this;
};
Base.prototype.mixin = function(key, val) {
Base.prototype[key] = val;
return this;
};
Base.prototype.mixins = Base.prototype.mixins || [];
Object.defineProperty(Base.prototype, 'base', {
configurable: true,
get: function() {
return this.parent ? this.parent.base : this;
}
});
define(Base, 'use', function(fn) {
fns.push(fn);
return Base;
});
define(Base, 'run', function(obj, prop, arr) {
var len = arr.length, i = 0;
while (len--) {
obj[prop](arr[i++]);
}
return Base;
});
define(Base, 'extend', cu.extend(Base, function(Ctor, Parent) {
Ctor.prototype.mixins = Ctor.prototype.mixins || [];
define(Ctor, 'mixin', function(fn) {
var mixin = fn(Ctor.prototype, Ctor);
if (typeof mixin === 'function') {
Ctor.prototype.mixins.push(mixin);
}
return Ctor;
});
define(Ctor, 'mixins', function(Child) {
Base.run(Child, 'mixin', Ctor.prototype.mixins);
return Ctor;
});
Ctor.prototype.mixin = function(key, value) {
Ctor.prototype[key] = value;
return this;
};
return Base;
}));
define(Base, 'mixin', function(fn) {
var mixin = fn(Base.prototype, Base);
if (typeof mixin === 'function') {
Base.prototype.mixins.push(mixin);
}
return Base;
});
define(Base, 'mixins', function(Child) {
Base.run(Child, 'mixin', Base.prototype.mixins);
return Base;
});
define(Base, 'inherit', cu.inherit);
define(Base, 'bubble', cu.bubble);
return Base;
}
module.exports = namespace();
module.exports.namespace = namespace;