/**
 * Register Schematic namespace
 * All internal references should use the full Schematic namespace
**/
var Schematic = window.Schematic || {};

/**
 * Inheritence helper for extending object prototypes
**/
Schematic.extend = function(subClass, superClass, objectExtend) {
	var F = function() {},
	    i;
	F.prototype = superClass.prototype; // Create temp class of super
	subClass.prototype = new F(); // chain sub with super
	subClass.prototype.constructor = subClass; // override constructor of super with sub
	subClass.superclass = superClass.prototype; // add superclass property to sub so it can call super if needed
	if (objectExtend) { 
		for (i in objectExtend) { // loop through extending object and assign methods/properties to the prototype
			subClass.prototype[i] = objectExtend[i];
		}
	}
};


/**
 * Registers a namespace
**/
Schematic.register = function(nameSpace) {
	var aNameSpace = nameSpace.split("."),
	    root = window,
	    i;
	for(i = 0; i < aNameSpace.length; i++) {
		// Test if object exists
		if(typeof root[aNameSpace[i]] == "undefined") {
			// create it				
			root[aNameSpace[i]] = {};
		}
		root = root[aNameSpace[i]];
	}
};


/**
 * On demand javascript lets you dynamically include scripts on your page 
 * without initially getting them in the document head. This is useful
 * because it allows you to only load essential scripts upfront and subsquent scripts
 * as needed.  Also useful for crossdomain AJAX.
 * 
 * @param {string} sUri  relative or fully qualified URI of the script you wish to load
 * @param {string} sMethod Currently only supports DOM based 
**/ 

Schematic.require = function(sUri, method) {
	var i, head, script;
	// Create cache of required scripts
	if (typeof this.required === "undefined") {
		this.required = [];
	}
	// test if script has already been required
	if (this.required.contains(sUri)) {
		return;
	}	
	switch (method) {
		case "dom" : 
		 	// create new script element in head
			head = document.getElementsByTagName("head")[0];
			script = document.createElement("script");
			script.setAttribute("charset", "utf-8");
			script.setAttribute("type", "text/javascript");
			script.setAttribute("src", sUri);
			head.appendChild(script);
			
			// Add to list of already included scripts
			this.required.push(sUri);
		break;
		
  		case "xhr": 
			// not yet impletmented, coming soon
		break;
			
		default: 
			this.require(sUri, "dom");
		break;
	}
};

/**
 * Sets a few basic Browser/DOM flags
**/
Schematic.Flag = {
	W3 : !!(document.getElementById && document.createElement),
	IE : /*@cc_on !@*/false,
	WK : !!(document.childNodes && !document.all && !navigator.taintEnabled), /* <-- Webkit */

	getIEVersion: function() {
		if (this.IE) {
			this.IE = {};
			this.IE.jscript/*@cc_on =@_jscript_version@*/;

			if (this.IE.jscript == 5.7) {
				this.IE7 = true;
			} else {
				this.IE6 = true;
			}
		}
	}
};
Schematic.Flag.getIEVersion();


/**
 * Merges a number of objects recursively with referencing them or their sub-objects
 * @param {object} object	Any number of objects
**/
Schematic.merge = function() {
	var i, prop, ap, mp, 
		mix = {};
		
	for (i = 0; i < arguments.length; i++) {
		for (prop in arguments[i]) {
			ap = arguments[i][prop];
			mp = mix[prop];
			if (mp && typeof ap === "object" && typeof mp === "object") {
				Schematic.merge(mp, ap);
			} else {
				mix[prop] = ap;
			}
		}
	}
	return mix;
};


/**
 * Turn off background image caching for IE 
**/

/*@cc_on document.execCommand("BackgroundImageCache", false ,true);@*/

if (!Array.prototype.push) {
	Array.prototype.push = function() {
		for (var i = 0, j = arguments.length; i < j; i++) {
			this[this.length] = arguments[i];
		}
		return this.length;
	};
}

if (!Array.prototype.pop) {
	Array.prototype.pop = function() {
		var lastElement = this[this.length - 1];
		this.length = Math.max(this.length - 1, 0);
		return lastElement;
	};
}

if (!Array.prototype.contains) {
	Array.prototype.contains = function(o) {
		for (var i = 0, j = this.length; i < j; i++) {
			if (this[i] === o) {
				return true;
			}
		}
		return false;
	};
}

if(!Array.prototype.indexOf){
    Array.prototype.indexOf = function(o, start) {
        for(var i = (start || 0); i < this.length; i++) {
            if(this[i] === o){
                return i;
            }
        }
    };
}

/**
 * forEach, version 1.0
 * Copyright 2006, Dean Edwards
 * License: http://www.opensource.org/licenses/mit-license.php
**/
if (!Array.forEach) { // mozilla already supports this
	Array.forEach = function(array, block, context) {
		for (var i = 0, j = array.length; i < j; i++) {
			block.call(context, array[i], i, array);
		}
	};
}

/**
 * Function.bind(), version 1.0
 * Written by Rob Kinyon, based on prototype.js by Sam Stephenson
**/
if (!Function.bind) {
	Function.prototype.bind = function(object) {
		var __method = this;
		return function() {
			return __method.call(object, arguments);
		};
	};
}

/**
 * Function.bindAsEventListener(), version 1.0
 * Written by Rob Kinyon, based on prototype.js by Sam Stephenson
**/
if (!Function.bindAsEventListener) {
	Function.prototype.bindAsEventListener = function(object) {
		var __method = this;
	 	return function(event) {
	  		return __method.call(object, event || window.event);
		};
	};
}