/*
===========================================================

CLASSERY

by Bogart Salzberg, Portland WebWorks

Classery tools help you encapsulate and reuse your code.

===========================================================
*/

(function () {

var classery = {

/*

Define any or all of these features in one call:
	constructor
	instance properties and methods
	class properties and methods
	superclass
	prototype

*/

def: function (_constructor, instance_spec, class_spec, superclass, prototype, rename) {
	var prototype =
		prototype ?
		prototype : 
			superclass ?
			new superclass() :
			{};
	_constructor.prototype = prototype;
	if (rename != undefined) {
		if (typeof _constructor.prototype.renamed != 'object') {
			_constructor.prototype.renamed = {};
		}
		for (var key in (rename || {})) {
			if (_constructor.prototype[key] == undefined) {
				throw 'No such property as ' + key;
			}
			_constructor.prototype.renamed[rename[key]] = _constructor.prototype[key];
		}
	}
	for (var key in (instance_spec || {})) {
		_constructor.prototype[key] = instance_spec[key];
	}
	for (var key in (class_spec || {})) {
		_constructor[key] = class_spec[key];
	}
	_constructor.prototype.superclass =
		superclass ?
		superclass :
		Object;
	return _constructor;
},

/*

Create a component object in target with all of the methods of window[sourceName].

For example, add a scout component to myApp:
	classery.employ(myApp, 'scout'); // now you can "myApp.scout.attend()"

Any scout method reference to "this" will be bound to the new myApp.scout object.

*/

employ: function (target, sourceName) {
	var employee = {};
	if (typeof window[sourceName] != 'object') {
		throw 'window.' + sourceName + ' is not an object';
	}
	source = window[sourceName];
	for (var key in source) {
		if (typeof source[key] != 'function') {
			continue;
		}
		employee[key] = source[key];
	}
	target[sourceName] = employee;
	return employee;
},

/*

Copy properties from source to target, optionally overwriting.

Use when target is a *wrapper* for source. For components, use employ().

*/

decorate: function (target, source, overwrite, ignore_existing) {
	for (var key in source) {
		if (typeof source[key] == 'function') {
			continue;
		}
		if (
		  (target[key] != undefined) &&
		  (overwrite !== true)
		) {
			if (ignore_existing) {
				continue;
			}
			throw 'Target object already has a "' + key + '" property';
		}
		target[key] = source[key];
	}
	return target;
},

/*

Copy methods from source to target, optionally overwriting.

Use when target is a *wrapper* for source. For components, use employ().

*/

mixin: function (target, source, overwrite, ignore_existing) {
	for (var key in source) {
		if (typeof source[key] != 'function') {
			continue;
		}
		if (
		  (target[key] != undefined) &&
		  (overwrite !== true)
		) {
			if (ignore_existing) {
				continue;
			}
			throw 'Target object already has a "' + key + '" method';
		}
		target[key] = source[key];
	}
	return target;
}

}; // end classery definition

window.classery = classery;

})(); // end module classery
