
// window.trackError = function(message, severity, extra) {
// 	var img;
// 	if (window.jQuery) {
// 		try{
// 			$.ajax({
// 				data: {
// 					type: 'javascript',
// 					severity: severity,
// 					message: message, 
// 					extra: extra
// 				},
// 				dataType: 'json',
// 				type: 'POST',
// 				url: '/log/error',
// 				error: function(XMLHttpRequest, textStatus, errorThrown) {
// 					img = new Image();
// 					img.src = "/log/img?severity=" + encodeURIComponent(severity) + "&message=" + encodeURIComponent(message);
// 				}
// 			});
// 		}catch(e){
// 			img = new Image();
// 			img.src = "/log/img?severity=" + encodeURIComponent(severity) + "&message=" + encodeURIComponent(message);
// 		}
// 		
// 	} else {
// 		img = new Image();
// 		img.src = "/log/img?severity=" + encodeURIComponent(severity) + "&message=" + encodeURIComponent(message);
// 	}
// };
// 
// window.onerror = function (message, url, line) {
// 	trackError(message, 'error', {line: line, url: url, handler: "window.onerror"});
// 	return true; // tell the browser that it doesn't need to handle the error
// };

window.RB = window.APP = (function(){

	// "cache" useful methods, so they don't
	// have to be resolved every time they're used
	var push = Array.prototype.push,
		slice = Array.prototype.slice,
		toString = Object.prototype.toString;


	var APP = {

		getQueryParameters: function() {
			var query = window.location.href.split('?')[1];

			//query won't be set if ? isn't in the URL
			if(!query) {
				return {};
			}

			var params = query.split('&');

			var pairs = {};
			for(var i = 0, len = params.length; i < len; i++) {
				var pair = params[i].split('=');
				pairs[pair[0]] = pair[1];
			}

			return pairs;
		},

		parseURL: function(url) {
			var a =  document.createElement('a');
			a.href = url;
			return {
				source: url,
				protocol: a.protocol.replace(':',''),
				host: a.hostname,
				port: a.port,
				query: a.search,
				params: (function(){
					var ret = {},
					seg = a.search.replace(/^\?/,'').split('&'),
					len = seg.length, i = 0, s;
					for (;i<len;i++) {
						if (!seg[i]) { continue; }
						s = seg[i].split('=');
						ret[s[0]] = s[1];
					}
					return ret;
				})(),
				file: (a.pathname.match(/\/([^\/?#]+)$/i) || [,''])[1],
				hash: a.hash.replace('#',''),
				path: a.pathname.replace(/^([^\/])/,'/$1'),
				relative: (a.href.match(/tps?:\/\/[^\/]+(.+)/) || [,''])[1],
				segments: a.pathname.replace(/^\//,'').split('/')
			};
		},

		/**
		 * Find and replace text
		 * 
		 * Usage:
		 *    A typical example would be when highlighting search keywords, here’s how that would work:
		 *    <code>
		 *    var searchMatch = document.referrer.match(/[?&]q=([^&]+)/),
		 *        searchTerm = searchMatch && searchMatch[1];
		 *    if (searchTerm) {
		 *        findAndReplace('\\b' + searchTerm + '\\b', function(term){
		 *            return '<span class="keyword">' + term + '</span>';
		 *        });
		 *    }
		 *    </code>
		 *    
		 *    <code>
		 *    findAndReplace('(microsoft|apple|sony)', '<a href="http://$1.com">$1</a>');
		 *    </code>
		 * 
		 * @author James Padolsey
		 * @link http://james.padolsey.com/javascript/find-and-replace-text-with-javascript/
		 * @param {String|Regex} searchText This can either be a string or a regular expression. Either way, it will eventually become a RegExp  object. So, if you wanted to search for the word “and” then that alone would not be appropriate – all words that contain “and” would be matched so you need to use either the string, \\band\\b or the regular expression, /\band\b/g to test for word boundaries. (remember the global flag)
		 * @param {String|Function} replacement will be directly passed to the String.replace function, so you can either have a string replacement (using $1, $2, $3 etc. for backreferences) or a function.
		 * @param {node} searchNode This parameter is mainly for internal usage but you can, if you so desire, specify the node under which the search will take place. By default it’s set to document.body
		 */
		findAndReplace: function(searchText, replacement, searchNode) {
			if (!searchText || typeof replacement === 'undefined') {
				// Throw error here if you want...
				return;
			}
			var regex = typeof searchText === 'string' ?
			new RegExp(searchText, 'g') : searchText,
			childNodes = (searchNode || document.body).childNodes,
			cnLength = childNodes.length,
			excludes = 'html,head,style,title,link,meta,script,object,iframe';
			while (cnLength--) {
				var currentNode = childNodes[cnLength];
				if (currentNode.nodeType === 1 &&
				(excludes + ',').indexOf(currentNode.nodeName.toLowerCase() + ',') === -1) {
					arguments.callee(searchText, replacement, currentNode);
				}
				if (currentNode.nodeType !== 3 || !regex.test(currentNode.data) ) {
					continue;
				}
				var parent = currentNode.parentNode,
				frag = (function(){
					var html = currentNode.data.replace(regex, replacement),
					wrap = document.createElement('div'),
					frag = document.createDocumentFragment();
					wrap.innerHTML = html;
					while (wrap.firstChild) {
						frag.appendChild(wrap.firstChild);
					}
					return frag;
				})();
				parent.insertBefore(frag, currentNode);
				parent.removeChild(currentNode);
			}
		},

		/**
		 * type checking / typeof replacement
		 * 
		 *     type(101);          // returns 'Number'
		 *     type('hello');      // returns 'String'
		 *     type({});           // returns 'Object'
		 *     type([]);           // returns 'Array'
		 *     type(function(){}); // returns 'Function'
		 *     type(new Date());   // returns 'Date'
		 *     type(document);     // returns 'HTMLDocument'
		 * 
		 */
		type: function(o){
		    return !!o && Object.prototype.toString.call(o).match(/(\w+)\]/)[1];
		},

		isArray:    function(o) { return !!o && ( Object.prototype.toString.call(o) === '[object Array]' ); },
		isFunction: function(o) { return !!o && ( Object.prototype.toString.call(o) === '[object Function]' ); },
		isObject:   function(o) { return !!o && ( Object.prototype.toString.call(o) === '[object Object]' ); },
		isString:   function(o) { return !!o && ( Object.prototype.toString.call(o) === '[object String]' ); },
		isNumber:   function(o) { return !!o && ( Object.prototype.toString.call(o) === '[object Number]' ); },

		randomHex: function() {
			return '#' + Math.floor( Math.random() * 16777215 ).toString(16);
		}

	};

	APP.toArray = (function() {
		// Return a basic slice() if the environment
		// is okay with converting NodeLists to
		// arrays using slice()
		try {
			slice.call(document.childNodes);

			return function(arrayLike) {
				return slice.call(arrayLike);
			};
		} catch(e) {}

		// Otherwise return the slower approach
		return function(arrayLike) {

			var ret = [],
				i = -1,
				len = arrayLike.length;

			while (++i < len) {
				ret[i] = arrayLike[i];
			}

			return ret;
		};
	})();  // end toArray

	return APP;
})();
