/* --------------------------------------------- */
/* ---------- Base Snatter JS Library ---------- */
/* --------------------------------------------- */

/* Copyright (c)2010 Stuart Wakefield, Snatter Ltd
 * Created:
 * Updated:
 */

( function() {

/*
 * 
 */	
 
	// Open snatter namespace
	var Snatter = window.Snatter = {};
	
	/* -------------------- */
	/* ----- Override ----- */
	/* -------------------- */
		/**
		 * Overrides a target objects members with properties from one or multiple sources
		 * @param {Object} target The target object to apply the source objects properties to
		 * @param {Object} source One or many source objects to copy properties from
		 * @return {Object} target Returns the original target object
		 */
		Snatter.override = function( target ) {
			var arr = Array.prototype.slice.call( arguments, 1 ),
				l = arr.length,
				i, x;
			// Loop through sources and properties and add them to 
			// the target object	
			for( i = 0; i < l; i ++ ) {
				for( x in arr[i] ) {
					target[x] = arr[i][x];
				}
			}
			// Return the target object
			return target;
		};
	/* [END] Override ----- */
	
	/* ----------------- */
	/* ----- Merge ----- */
	/* ----------------- */
		/** 
		 * Merges properties from one or multiple sources to a target object
		 * @param {Object} target The target object to apply the source objects properties to
		 * @param {Object} source One or many source objects to copy properties from
		 * @return {Object} target Returns the original target object
		 */
		Snatter.merge = function( target ) {
			var arr = Array.prototype.slice.call( arguments ),
				r = {},
				i, x;
			// Loop through source objects (in reverse) and 
			// properties and add the properties to the temporary
			// object literal
			for( i = arr.length; i !== 0; i -- ) {
				for( x in arr[i] ) {
					r[x] = arr[i][x];
				}
			}
			// Add the members from the object literal to the
			// target object
			for( x in r ) {
				target[x] = r[x];
			}
			// Return the target object
			return target;
		};
	/* [END] Merge ----- */
	
	/* ------------------ */
	/* ----- Extend ----- */
	/* ------------------ */
		/**
		 * Simplifies extension of classes and object literals new class object inherits from base object or class
		 * @param {Object/Function} base The base class/object to extend
		 * @param {Object/Function} construct The new class/object to inherit from the base class/object
		 * @param {Object} [proto] The class prototype if the construct param passed is a class
		 * @return {Object/Function} construct Returns the original class/object
		 */
		Snatter.extend = function( base, construct, proto ) {
			var blank = function() {};
			// Base object is an object literal return an object
			// literal that inherits from the base object including
			// the properties from the construct object
			if( typeof base === "object" ) {
				blank.prototype = base;
				blank = new blank;
				return Snatter.override( blank, construct );
			// Base object is a class return a new class that
			// inherits from the base object	
			} else {
				if( typeof construct === "object" ) {
					proto = construct;
					construct = proto.constructor === Object.prototype.constructor ? function() {
						base.apply( this, arguments );
					} : proto.constructor;
				}
				proto = proto || construct.prototype;
			}
			// Assign prototype, add to blank function
			// so that we can avoid calling the constructor
			// chain
			blank.prototype = base.prototype;
			construct.prototype = new blank;
			construct.prototype.constructor = construct;
			// Add pointer to super class prototype
			construct._super = base.prototype;
			// Add in properties from prototype
			Snatter.override( construct.prototype, proto );
			// Return new class
			return construct;
		};
	/* [END] Extend ----- */
	
	/* --------------------- */
	/* ----- Namespace ----- */
	/* --------------------- */
		/**
		 * Create or retrieve namespace, depending on whether it already exists. Pass a string with dot notation
		 * @param {String} path The dot notation path to the namespace to create or retrieve
		 * @return {Object} current The resolved namespace
		 */ 
		Snatter.namespace = function( path ) {
			var current = window,
				arr = path.split( /\./ ),
				l = arr.length,
				i;
			// Loop through path steps and create or repoint
			// current to next step up
			for( i = 0; i < l; i ++ ) {
				if( typeof current[ arr[i] ] === "undefined" ) {
					current[ arr[i] ] = {};
				}
				current = current[ arr[i] ];
			}
			// Return current pointer
			return current;
		};
	/* [END] Namespace ----- */

} ) ();
/* -----[END] Base Snatter JS Library ---------- */