 // Dependencies
 //		jquery.js >= 1.2.6

 (function($) {
	
	// Arrays
	$.inject = function(array, memo, fn) {
		for(var i = 0; i < array.length; i++)
			memo = fn(memo, array[i], i);

	    return memo;
	};
	
	$.flatten = function(array) {
		return $.inject(array, [], function(memo, value) {
			return memo.concat($.isArray(value) ? $.flatten(value) : [value]);
		});
	};
	
	$.select = function(array, fn) {
		var returns = [];
		
		for(var i = 0; i < array.length; i++)
			fn(array[i], i) && returns.push(array[i]);
		
		return returns;
	}
	
	$.compact = function(array) {
		return $.select(array, function(value) { return !!value; });
	}
	
	$.uniq = function(array) {
		return $.inject(array, [], function(arr, val) {
			if ($.inArray(val, arr) === -1) { arr.push(val); }
      		return arr;
		});
	}
	
	$.isArray = function(obj) {
		return Object.prototype.toString.call(obj) === "[object Array]";
	}

	
	// Functions
	$.curry = function() {
		var argsArray = Array.prototype.slice.call(arguments),
			fn = argsArray.shift();
		
		return function() {
			return fn.apply(this, argsArray.concat(Array.prototype.slice.call(arguments)));		
		};
	};
	
	
	// Objects
	function map(obj, fn) {
		var returns = [];
		$.each(obj, function() {
			var argsArray = Array.prototype.slice.call(arguments);
			returns.push(fn.apply(this, argsArray));
		});
		return returns;
	}
	
	$.obj = {
		map: map,
		keysFor: function(obj) {
			return map(obj, function(property) { return property; });
		},
		valuesFor: function(obj) {
			return map(obj, function(property, value) { return value; });
		}
	};
	
	$.isEmptyObject = function (obj) {
		for (var name in obj) {
			return false;
		}
		return true;
	};
	
	
	// jQuery
	$.coalesce = function() {
		var argsArray = Array.prototype.slice.call(arguments),
			returnValue = null;
		
		$.each(argsArray, function() {
			var $tmp = $(this);
			
			if(!returnValue && $tmp.length)
				returnValue = $tmp;
		});
		
		return returnValue;
	};
	
	
	// String
	$.supplant = function(template, data) {
		return template.replace(/{([^{}]*)}/g,
	        function (a, b) {
	            var r = data[b];
	            return typeof r === 'string' || typeof r === 'number' ? r : a;
	        }
	    );
	};
	
	$.w = function(string) { return string.split(' '); };
	
	$.capitalize = function(str) {
		return str.charAt(0).toUpperCase() + str.substring(1).toLowerCase();
	}
	

	// Namespace
	$.namespace = function(name) {
		var namespaces = name.split('.');
		return $.inject(namespaces, null, function(lastNamespace, currentNamespace) {
			lastNamespace = lastNamespace || window;
			lastNamespace[currentNamespace] = lastNamespace[currentNamespace] || {};

			return lastNamespace[currentNamespace];
		});
	}

	// Event
	$.delay = (function() {
		var timers = {};
		return function(callback, time) {
			clearTimeout(timers[callback]);
			timers[callback] = setTimeout(callback, time);
		}
	})();
})(jQuery);
