/**********************************************************************
* 
*
*
**********************************************************************/

define(function(require){ var module = {}

//var DEBUG = DEBUG != null ? DEBUG : true



/*********************************************************************/


// Make a JavaScrip object constructor...	
//
//
// 	Make a constructor with an object prototype...
// 		makeConstructor(<name>, <proto>)
// 			-> constructor
//
// 	Make a constructor with an init function prototype...
// 		makeConstructor(<name>, <init-func>)
// 			-> constructor
//
// 	Make a constructor with a prototype (object/function) and a class
// 	prototype...
// 		makeConstructor(<name>, <proto>, <class-proto>)
// 		makeConstructor(<name>, <init-func>, <class-proto>)
// 			-> constructor
// 			NOTE: the <class-proto> defines a set of class methods and 
// 					attributes.
//
//
//
// The resulting constructor can produce objects in one of these ways:
//
// 	Basic constructor use...
// 		constructor()
// 		new constructor
// 		new constructor()
// 			-> instance
//
// 	Pass arguments to the constructor...
// 		constructor(<arg>[, ...])
// 		new constructor(<arg>[, ...])
// 			-> instance
//
//
// All produced objects are instances of the constructor
// 		instance instanceof constructor
// 			-> true
//
//
//
// Init protocol:
// 	1) the base instance object is prepared (.__proto__ is set)
// 	2) if <init-func> is present, then it is called with instance as 
// 		context and passed the constructor arguments
// 	3) if <proto>.__init__(..) is present, it is called with the instance
// 		as context and passed the constructor arguments.
//
//
//
// Inheritance:
// 	A simple way to build C -> B -> A chain would be:
//
// 		var A = makeConstructor('A', {})
//
// 		// NOTE: the prototype is an instance and not a constructor,
// 		//		this is obvious if one considers that in JS there are
// 		//		no classes and inheritance is done via object prototypes
// 		//		but this might be a gotcha to people coming from the 
// 		//		class-object world.
// 		var B = makeConstructor('B', A())
//
// 		var C = makeConstructor('C', B())
//
// 		var c = C()
//
// 		c instanceof C		// -> true
// 		c instanceof B		// -> true
// 		c instanceof A		// -> true
//
// 		A.prototype.x = 123
//
// 		c.x 				// -> 123
//
//
//
// Motivation:
// 	The general motivation here is to standardise the constructor protocol
// 	and make a single simple way to go with minimal variation. This is due
// 	to the JavaScript base protocol though quite simple, being too flexible
// 	making it very involved to produce objects in a consistent manner by 
// 	hand, especially in long running projects, in turn spreading all the 
// 	refactoring over multiple sites and styles.
//
// 	This removes part of the flexibility and in return gives us:
// 		- single, well defined protocol
// 		- one single spot where all the "magic" happens
// 		- full support for existing JavaScript ways of doing things
// 		- easy refactoring without touching the client code
//
//
// XXX might be a good idea to be able to make an instance without 
// 		initializing it...
// 		...mainly for inheritance.
// 		...would also be helpful in this case to call all the 
// 		constructors in the chain
var makeConstructor =
module.makeConstructor =
function makeConstructor(name, a, b){
	var proto = b == null ? a : b
	var cls_proto = b == null ? b : a

	var _constructor = function Constructor(){
		/*
		// XXX BUG: if the constructor is called from it's instance this will 
		// 		return the instance and not a new object...
		// in case this is called as a function (without new)...
		if(this.constructor !== _constructor){
			// NOTE: the following does the job of the 'new' operator but
			// 		with one advantage, we can now pass arbitrary args 
			// 		in...
			// 		This is equivalent to:
			//			return new _constructor(json)
			var obj = {}
			obj.__proto__ = _constructor.prototype
			// XXX for some reason this does not resolve from .__proto__
			obj.constructor = _constructor
			//obj.__proto__.constructor = _constructor

		} else {
			var obj = this
		}
		*/

		// NOTE: the following does the job of the 'new' operator but
		// 		with one advantage, we can now pass arbitrary args 
		// 		in...
		// 		This is equivalent to:
		//			return new _constructor(json)
		var obj = {}
		obj.__proto__ = _constructor.prototype
		// XXX for some reason this does not resolve from .__proto__
		// XXX this also is a regular attr and not a prop...
		//obj.constructor = _constructor
		Object.defineProperty(obj, 'constructor', {
			value: _constructor,
			enumerable: false,
		})
		//obj.__proto__.constructor = _constructor

		// explicit init...
		if(proto instanceof Function){
			proto.apply(obj, arguments)
		}

		// load initial state...
		if(obj.__init__ != null){
			obj.__init__.apply(obj, arguments)
		}

		return obj
	}

	// this is here to make Chrome output more user friendly...
	// skip for IE...
	if(_constructor.name == 'Constructor'){
			// skip for chrome app...
			//&& !(window.chrome && chrome.runtime && chrome.runtime.id)){
		eval('_constructor = '+ _constructor
				.toString()
				.replace(/Constructor/g, name))
	}

	_constructor.__proto__ = cls_proto
	_constructor.prototype = proto
	_constructor.prototype.constructor = _constructor

	return _constructor
}


// super equivalent...
//
// 	superMethod(<class>, <method-name>).call(this, ...)
// 		-> <result>
//
// This will return a next method in inheritance chain after <class> by
// its name (<method-name>).
// In the normal use-case <class> is the current class and <method-name>
// is the name of the current method.
var superMethod =
module.superMethod =
function superMethod(cls, meth){
	return cls.prototype.__proto__[meth]
}



/**********************************************************************
* vim:set ts=4 sw=4 :                                                */
return module })
