/*-----------------------------------------------------------------------------
 APPLICATION HELPER
 version:			1.0
 date:				18/08/09
 author:			Florian Plank
 website:			http://www.fusion.fi
 -----------------------------------------------------------------------------*/

/* DEBUGGING HELPERS
 * ---------------------------------------------------------------------------*/

/**
 * Prints message to Firebug console or
 * as alert, if Firebug is not installed
 * 
 * @param String m Message to be logged
 * @param String t Type of message
 * @return String
 */
var ENV = ENV || 'development';

// Fix for IE
if ($.browser.msie) {
	window.console = { log: function(){} };
}

function _(m, t) {
	var type = ( t == 'error' || t == 'info' || t == 'warn' || t == 'debug' ) ? t : 'log';
	var label = (type.substr(0, 1).toUpperCase() + type.substr(1, type.length)).toUpperCase();

	if( ENV == 'development' )
	{
		if ( !$.browser.msie && console && typeof console.log == 'function') {
			console[type](m);
		} else {
			if (type == 'error') {
				alert("ERROR; " + label + ": " + m);
			}
		}
		return label + ": " + m;
	}
	else if ( ENV == 'production' ) {}
}

// Additional methods
_e = function (m) { _(m, 'error'); };
_i = function (m) { _(m, 'info'); };
_w = function (m) { _(m, 'warn'); };
_d = function (m) { _(m, 'debug'); };

String.prototype.padLeft = function(paddedLength, padChar) {
	var str = this;
	padChar = padChar || '0';
	while (paddedLength > str.length) {
		str = padChar + str;
	}
	return str;
};

/**
 * Convert string in camel format to file format
 * 
 * EXAMPLE:
 * 
 * "ConvertThisNow" => "convert_this_now"
 */
String.prototype.camelToUnderscore= function() {
	return this.replace(/([a-z])(?=[A-Z])/g, "$1_").toLowerCase();
};

/**
 * Convert string in camel format to css class format
 * 
 * EXAMPLE:
 * 
 * "ConvertThisNow" => "convert-this-now"
 */
String.prototype.camelToDash= function() {
	return this.replace(/([a-z])(?=[A-Z])/g, "$1-").toLowerCase();
};

/**
 * Truncate string
 * 
 * EXAMPLE:
 * 
 * var str = "This is a test for my truncation method.";
 * str.truncate(10") // -> "This is a t&hellip;"
 * str.truncate(10, true, "[...]") // -> "This is a[...]"
 * 
 */
String.prototype.truncate = function(len, preserveWords, app) {
	var str = this;
	var defaultApp = '&hellip;';
	app = typeof app == 'undefined' ? defaultApp : app;

	if( str.length < len ) {
		return str;
	}

	if( ! preserveWords ) {
		return str.substr(0, ( app == defaultApp) ? len - 1 : len - app.length ) + app;
	}

	str = str.replace(/\s+/i, ' ').replace(/\r\n/i, ' ').replace(/\r/i, ' ').replace(/\n/i, ' ');

	if( str.length < len ) {
		return str;
	}

	var truncatedString = '';
	var words = str.trim().split(' ');

	for(var i=0; i<words.length; i++)
	{
		truncatedString += words[i] + ' ';
		if (truncatedString.length >= len)
		{
			truncatedString = truncatedString.trim();
			return ( truncatedString.length == str.length ) ? truncatedString :	truncatedString + app;
		}
	}
};

/**
 * Trim white space from beginning and end of string
 * 
 * EXAMPLE:
 * 
 * var str = "			This is a short string.		";
 * str.trim(); // -> "This is a short string.";
 * 
 */
String.prototype.trim = function() {
	return this.replace(/^\s+|\s+$/g, '');
};

String.prototype.toCSSClass = function() {
	return this.replace(/::/g, '-').replace(/-/g, '-').replace(/,/g, '-').replace(/\s+/g,'-').toLowerCase();
};

String.prototype.toVarName = function() {
	var bits = [];
	var string = this.replace(/::/g, '_').replace(/-/g, '_').replace(/-/g, '_').replace(/\s+/g,'').toLowerCase();

	jQuery.each(string.split("_"), function(key, value){
		if (key == 0) 
			bits[key] = value;
		else 
			bits[key] = value[0].toUpperCase() + value.substr(1, value.length);
	});
	return bits.join('');
};

/**
 * Filter element in array
 * 
 * EXAMPLE:
 *
 *	var result = ['dustin', 'robert', 'virus', 'vince'].filter(
 *		function(el, i, ar) {
 *			if ( el !== 'virus' ) {
 *				return el;
 *			}
 *		}
 *	};
 *
 * Source: Justin Diaz, http://www.dustindiaz.com/basement/sugar-arrays.html 
 */
Array.prototype.filter = function(fn, thisObj) {
	var scope = thisObj || window;
	var a = [];
	for ( var i=0, j=this.length; i < j; ++i ) {
		if ( !fn.call(scope, this[i], i, this) ) {
			continue;
		}
		a.push(this[i]);
	}
	return a;
};

/**
 * Find element in array
 * 
 * EXAMPLE:
 * 
 * var a = [2, 5, 9], index;
 * index = a.indexOf(2); // index is 0
 * index = a.indexOf(7); // index is -1
 * 
 * Source: Justin Diaz, http://www.dustindiaz.com/basement/sugar-arrays.html 
 */
Array.prototype.indexOf = function(el, start) {
	start = start || 0;
	for ( var i=0; i < this.length; ++i ) {
		if ( this[i] === el ) {
			return i;
		}
	}
	return -1;
};

/**
 * Find last occurance of element in array
 * 
 * EXAMPLE:
 * 
 * var a = [2, 5, 9, 2], i;
 * i = a.lastIndexOf(2); // i is: 3
 * i = a.lastIndexOf(7); // i is: -1
 * 
 * Source: Justin Diaz, http://www.dustindiaz.com/basement/sugar-arrays.html 
 */
Array.prototype.lastIndexOf = function(el, start) {
	start = start || this.length;
	if ( start >= this.length ) {
		start = this.length;
	}
	if ( start < 0 ) {
		start = this.length + start;
	}
	for ( var i=start; i >= 0; --i ) {
		if ( this[i] === el ) {
			return i;
		}
	}
	return -1;
};

/**
 * Get first element in array
 */
Array.prototype.first = function() {
	return this[0];
};

/**
 * Get last element in array
 */
Array.prototype.last = function() {
	return this[this.length-1];
};

Array.prototype.max = function() {
	var max = this[0];
	for( var i=0; i<this.length; i++ ) {
		max = max < this[i] ? this[i] : max;
	}
	return max;
};

Array.prototype.min = function() {
	var min = this[0];
	for( var i=0; i<this.length; i++ ) {
		min = min > this[i] ? this[i] : min;
	}
	return min;
};

/**
 * Iterate through array
 */
Array.prototype.each = function(iterator){
	for (var j = 0, length = this.length; j < length; j++) {
		iterator(j, this[j]);
	}
};

function keys(object) {
	var results = [];
	for (var property in object) {
		results.push(property);
	}
	return results;
}

function values(object) {
	var results = [];
	for (var property in object) {
		results.push(object[property]);
	}
	return results;
}

/**
 * Date helpers
 */
String.prototype.isISO8601Date = function() {
 var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})" +
	"(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?" +
	"(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?";
 return this.match(new RegExp(regexp)) ? true : false;
};

Date.prototype.setISO8601 = function(string) {
	var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})" +
	"(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?" +
	"(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?";
	var d = string.match(new RegExp(regexp));
	var offset = 0;
	var date = new Date(d[1], 0, 1);
	
	if (d[3]) {
		date.setMonth(d[3] - 1);
	}
	if (d[5]) {
		date.setDate(d[5]);
	}
	if (d[7]) {
		date.setHours(d[7]);
	}
	if (d[8]) {
		date.setMinutes(d[8]);
	}
	if (d[10]) {
		date.setSeconds(d[10]);
	}
	if (d[12]) {
		date.setMilliseconds(Number("0." + d[12]) * 1000);
	}
	if (d[14]) {
		offset = (Number(d[16]) * 60) + Number(d[17]);
		offset *= ((d[15] == '-') ? 1 : -1);
	}
	
	offset -= date.getTimezoneOffset();
	time = (Number(date) + (offset * 60 * 1000));
	this.setTime(Number(time));
};


// returns GET parameter from URL
function getURLparameter(name){
    name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
    var regexS = "[\\?&]" + name + "=([^&#]*)";
    var regex = new RegExp(regexS);
    var results = regex.exec(window.location.href);
    if (results == null) 
        return "";
    else 
        return results[1];
}


// Convertes hash with keys in dot-notation into nested objects
var toNestedObject = function(hash) {
	var returnObject = {};
	for(key in hash) {
	    var scope = returnObject;
	    var keyTree = key.split('.');
	    for(var i=0; i<keyTree.length; i++) {
	        if(i==keyTree.length-1) {
	            scope[keyTree[i]] = hash[key];
	        } else
			if(scope[keyTree[i]] == undefined) {
	            scope[keyTree[i]] = {};
	        }
	        scope = scope[keyTree[i]];
	    }
	}
	return returnObject;
};
