/////////////////////////////////////////////////////
//	NObject object
//
function NObject()
{
	if(String(this.length) == "undefined")
		throw "Cannot create a direct instance of NObject";

	NObject.prototype.RuntimeType = this;
	NObject.prototype.RuntimeTypeName = NObject.extractTypeName();
	NObject.prototype.BaseType = null;
	NObject.prototype.BaseTypeName = null;
}

NObject.prototype.InitializeRuntimeTypeInfo = function(prototype)
{
	this.length = 6;
	if(String(this.RuntimeType) != "undefined")
		return;

	this.RuntimeType = prototype.RuntimeType;
	this.RuntimeTypeName = prototype.RuntimeTypeName;
	this.BaseType = prototype.BaseType;
	this.BaseTypeName = prototype.BaseTypeName;
}

//	Returns the current type runtime information
NObject.prototype.GetType = function()
{
	return this.RuntimeType;
}

//	Returns the current type name
NObject.prototype.GetTypeName = function()
{
	return this.RuntimeTypeName;
}

//	Returns the base type
//	There is a slight difference between a type and type's prototype
//	The type e.g. this.BaseType provides the static definitions as properties/methods
//	The type e.g. this.BaseType.prototype provides the instance definitions as properties/methods
NObject.prototype.GetBase = function()
{
	return this.BaseType.prototype;
}

//	Returns the base type runtime information
NObject.prototype.GetBaseType = function()
{
	return this.BaseType;
}

//	Returns the base type name
NObject.prototype.GetBaseTypeName = function()
{
	return this.BaseTypeName;
}

/////////////////////////////////////////////////////
//	General purpose jscript configuration
//
function mustoverride()
{
	throw "Must override.";
}

Function.prototype.DeriveFrom = function(baseType)
{
	var prop;

	if(this == baseType)
		throw "Cannot derive from self";

	//	derive instance members
	for(prop in baseType.prototype)
		if(typeof(baseType.prototype[prop]) == "function" && !this.prototype[prop])
			this.prototype[prop] = baseType.prototype[prop];

	//	derive static members
	for(prop in baseType)
		if(typeof(baseType[prop]) == "function" && !this.prototype[prop])
			this[prop] = baseType[prop];
			
	this.prototype.RuntimeType = this;
	this.prototype.RuntimeTypeName = this.extractTypeName();

	this.prototype.BaseType = baseType;
	this.prototype.BaseTypeName = baseType.extractTypeName();

	this.prototype[this.prototype.BaseTypeName] = baseType;
}

Function.prototype.extractTypeName = function()
{
    var typeName;
    typeName = this.toString();
    typeName = typeName.substring(typeName.indexOf(" ") + 1, typeName.indexOf("("))
    return typeName;
}

Function.prototype.GetType = function()
{
	return this.prototype.RuntimeType;
}

Function.prototype.GetTypeName = function()
{
	return this.prototype.RuntimeTypeName;
}

Function.prototype.GetBaseType = function()
{
	return this.prototype.BaseType;
}

Function.prototype.GetBaseTypeName = function()
{
	return this.prototype.BaseTypeName;
}
