/**
is(),
XO,
@author bibby
@requires XUtil.js
**/



/**
@author Crockford , bibby
A better typeof. Accurately returns null and array.
Can also be used as an "is_a" or a simple test for truth.
examples:
	var foo = 'bar';
	is(foo); // true;
	is(foo,'string'); // true
	is(foo,'type'); // string
@param mixed variable
@param string (optional) data type
**/
var is = function (v,type)
{
	switch(typeof type)
	{
		case 'undefined':
			return !!v;
			break;
		case 'function':
			return v instanceof type ? true : false;
	}
	
	
	type=type.toLowerCase();
	if(type == 'nan')
	{
		return isNaN(v);
	}
	
	var vt = typeof v;
	if(vt === 'object')
	{
		if(v)
		{
			if (typeof v.length === 'number' && !(v.propertyIsEnumerable('length')) && typeof v.splice === 'function') 
				vt = 'array';
			
			// last chance to return new Number() as a number :P
			if(v instanceof Number)
				vt = 'number';
			if(v instanceof String)
				vt = 'string';
			if(v instanceof Boolean)
				vt = 'boolean';
		}
		else
		{
			vt = 'null';
		}
	}
	
	if(type=="type")
		return vt;
	
	return vt == type ? true : false;
};






/** XO - eXtendable Object

.extend   // extend this instace from object
.extendClass // extend this instance from class
.xo  // static (new XO's don't have this) Accepts an object and gives it extend and extendClass
.x // static (new XO's don't have this) Extends an object by another object without giving it extend()

The alternative to Object.prototype.extend , which can create as many problems as it solves

XO may be used to create a singleton by making a new XO:
	var foo = new XO(members);  // members being an object of members {}

That object may now extend from other objects ( foo.extend(bar) ) or from classes that
take no parameters to be constructed ( foo.extendClass( Bar ) )

XO may be used in a class to have its instances be extendable using xo():
	function className(members)
	{
		XO.xo(this).extend(members);
	}
	
XO may also use its extend methods to apply members to new Objects without gifting 
the extend functions themselves with XO.x(obj,members)

You do NOT want to extend the var XO. Make your own instance [ new XO() ] or use .xo , .x

"Yes, we're tired. 
 Yes, there is no relief. 
 Yes, the Cylons keep coming after us time after time after time. 
 And yes, we are still expected to do our jobs!" 
	 - Saul Tigh, XO
*/

var XO = function(members)
{
	/*
	@param object to extend from
	@param boolean , overwrite existing members? (default is false)
	*/
	this.extend = function(o,over)
	{
		if(!is(o,'object'))
			return this;
		for(var i in o)
			if(is(over) || (!is(over) && !(i in this)))
				this[i]=o[i];
		return this;
	};
	
	// extend XO further
	this.extend({
		
		/*
		object extend from a class name by making a new instance
		@param mixed function (class) or object to extend from
		@param boolean , overwrite existing members?
		*/
		extendClass:function(cls,over)
		{
			if(is(cls,'function'))
			{
				try
				{
					this.extend(new cls,over);
				}
				catch(e)
				{
					return e;
				}
			}		
			else if(!is(cls,'object'))
				this.extend(cls,over);
			return this;
		}
	});
	
	
	// finally, if any members were given to the XO constructor, apply these.
	if(is(members,'object'))
		this.extend(members,true);
};

// STATIC functions given to objects from the constructor
/*
use XO to make an object extendable itself
@param object , any
@return object , same, only with extend methods
*/
XO.xo=function(obj)
{
	if(!is(obj,'object'))
		obj={};
	if(is(obj.extend,'function'))
		return obj;
	
	xo = new XO();
	obj.extend = xo.extend;
	obj.extendClass = xo.extendClass;
	return obj;
},

/*
use XO to extend another object without giving it extend()
@param object to extend
@param object members/methods to grant
*/
XO.x=function(obj,members)
{
	if(!is(members,'object'))
		return obj;
	for(var i in members)
	{
		try{obj[i]=members[i]}
		catch(e){ console.log('counldnt copy '+members[i], i, e);};
	}
	return obj;
}

