/**
 * Acadam JavaScript Functions
 *
 * @author Gabriel Lemonde-Labrecque
 * @copyright 2010, SchoolSuccess inc.
 */

/**
 * Declaration of the global Acadam variable used in most JS files
 */
var TC = {
	data: {},
	string: {},
	ajax: {},
	errors: {},
	html: {},
	debug: {},
	form: {}
};

TC.lang = {
	/**
	 * TC.lang.get
	 */
	get: function(index) {
		if (typeof eval('TC.lang.' + index) == 'string') {
			return eval('TC.lang.' + index);
		}
		
		return '';
	},
	
	/**
	 * TC.lang.set
	 */
	set: function(index, value) {
		TC.language[index] = value;
	}
};

/**
 * TC.string.trim
 * 
 * Strip whitespace from the beginning and end of a string
 */
TC.string.trim = function(str) {
	str = str.replace(/^\s+/, '');
	for (var i = str.length - 1; i >= 0; i--) {
		if (/\S/.test(str.charAt(i))) {
			str = str.substring(0, i + 1);
			break;
		}
	}
	return str;
}; // End of TC.string.trim

TC.string.trimTextByHeight = function($object, maxHeight) {
	var attr = ['font-family', 'font-size', 'font-weight', 'font-style',
	            'text-transform', 'text-decoration', 'letter-spacing',
	            'word-spacing', 'line-height', 'text-align', 'direction',
	            'width', 'margin-top', 'margin-right', 'margin-bottom',
	            'margin-left', 'padding-top', 'padding-right', 'padding-bottom',
	            'padding-left', 'border-top-width', 'border-right-width',
	            'border-bottom-width', 'border-left-width', 'border-top-style',
	            'border-right-style', 'border-bottom-style',
	            'border-left-style'];
	
	$object.each(function() {
		var cssProperties = {};
		for (var i = 0; i < attr.length; i++)
			cssProperties[attr[i]] = jQuery.fn.css.call(this, attr[i]);
		
		var $cloned = $('<div></div>');
		$('body').eq(0).append($cloned);
		$cloned.css({ 'display': 'none', 'width': $(this).width() });
		
		var text = $(this).html();
		$cloned.html(text);
		$cloned.css(cssProperties);
		
		var clonedHeight = $cloned.height();
		
		if (clonedHeight > maxHeight)
		{
			text = text.substring(0, text.length / clonedHeight * maxHeight);
			
			for (var currentHeight = clonedHeight; currentHeight > maxHeight; currentHeight = $cloned.height())
			{
				// Remove a word
				text = text.substring(0, text.lastIndexOf(' '));
				
				$cloned.html(text + '...');
			}
		}
		
		$cloned.remove();
		
		$(this).html($cloned.html());
	});
};

/**
 * TC.string.stripTags
 * 
 * Strip HTML and PHP tags from a string
 */
TC.string.stripTags = function(str, allowed_tags) {
	// http://kevin.vanzonneveld.net
	// +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	// +   improved by: Luke Godfrey
	// +      input by: Pul
	// +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	// +   bugfixed by: Onno Marsman
	// +      input by: Alex
	// +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	// +      input by: Marc Palau
	// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	// +      input by: Brett Zamir (http://brett-zamir.me)
	// +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	// +   bugfixed by: Eric Nagel
	// +      input by: Bobby Drake
	// +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	// +   bugfixed by: Tomasz Wesolowski
	// *     example 1: strip_tags('<p>Kevin</p> <br /><b>van</b> <i>Zonneveld</i>', '<i><b>');
	// *     returns 1: 'Kevin <b>van</b> <i>Zonneveld</i>'
	// *     example 2: strip_tags('<p>Kevin <img src="someimage.png" onmouseover="someFunction()">van <i>Zonneveld</i></p>', '<p>');
	// *     returns 2: '<p>Kevin van Zonneveld</p>'
	// *     example 3: strip_tags("<a href='http://kevin.vanzonneveld.net'>Kevin van Zonneveld</a>", "<a>");
	// *     returns 3: '<a href='http://kevin.vanzonneveld.net'>Kevin van Zonneveld</a>'
	// *     example 4: strip_tags('1 < 5 5 > 1');
	// *     returns 4: '1 < 5 5 > 1'
	
	var key = '', allowed = false;
	var matches = [];
	var allowed_array = [];
	var allowed_tag = '';
	var i = 0;
	var k = '';
	var html = '';
	
	var replacer = function (search, replace, str) {
	  return str.split(search).join(replace);
	};
	
	// Build allowes tags associative array
	if (allowed_tags) {
	  allowed_array = allowed_tags.match(/([a-zA-Z0-9]+)/gi);
	}
	
	str += '';
	
	// Match tags
	matches = str.match(/(<\/?[\S][^>]*>)/gi);
	
	// Go through all HTML tags
	for (key in matches) {
	  if (isNaN(key)) {
			// IE7 Hack
			continue;
		}
		
		// Save HTML tag
		html = matches[key].toString();
		
		// Is tag not in allowed list? Remove from str!
		allowed = false;
		
		// Go through all allowed tags
		for (k in allowed_array) {
			// Init
			allowed_tag = allowed_array[k];
			i = -1;
			
			if (i != 0) { i = html.toLowerCase().indexOf('<'+allowed_tag+'>');}
			if (i != 0) { i = html.toLowerCase().indexOf('<'+allowed_tag+' ');}
			if (i != 0) { i = html.toLowerCase().indexOf('</'+allowed_tag)   ;}
			
			// Determine
			if (i == 0) {
				 allowed = true;
				 break;
			}
		}
		
		if ( ! allowed) {
			str = replacer(html, "", str); // Custom replace. No regexing
		}
	}
	
	return str;
}; // End of TC.string.stripTags

TC.string.url = {
	// public method for url encoding
	encode : function (string) {
		return escape(this._utf8_encode(string));
	},
	
	// public method for url decoding
	decode : function (string) {
		return this._utf8_decode(unescape(string));
	},
	
	// private method for UTF-8 encoding
	_utf8_encode : function (string) {
		string = string.replace(/\r\n/g,"\n");
		var utftext = "";
		
		for (var n = 0; n < string.length; n++) {
			
			var c = string.charCodeAt(n);
			
			if (c < 128) {
				utftext += String.fromCharCode(c);
			}
			else if ((c > 127) && (c < 2048)) {
				utftext += String.fromCharCode((c >> 6) | 192);
				utftext += String.fromCharCode((c & 63) | 128);
			}
			else {
				utftext += String.fromCharCode((c >> 12) | 224);
				utftext += String.fromCharCode(((c >> 6) & 63) | 128);
				utftext += String.fromCharCode((c & 63) | 128);
			}
			
		}
		
		return utftext;
	},
	
	// private method for UTF-8 decoding
	_utf8_decode : function (utftext) {
		var string = "";
		var i = 0;
		var c = c1 = c2 = 0;
		
		while ( i < utftext.length ) {
			c = utftext.charCodeAt(i);
			
			if (c < 128) {
				string += String.fromCharCode(c);
				i++;
			}
			else if((c > 191) && (c < 224)) {
				c2 = utftext.charCodeAt(i+1);
				string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
				i += 2;
			}
			else {
				c2 = utftext.charCodeAt(i+1);
				c3 = utftext.charCodeAt(i+2);
				string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
				i += 3;
			}
		}
		
		return string;
	}
}; // End of TC.string.url

TC.string.jsonDecode = function(jsonString) {
	if ( ! jsonString)
		return false;
	
	return eval('(' + jsonString + ')');
}; // End of TC.string.jsonDecode


/**
 * TC.ajax.send
 *
 * Perform an Ajax call
 *
 * @param string url The URL to call with Ajax
 * @param string type Either POST or GET
 * @param mixed data The data sent to the url
 * @param string dataType e.g. 'json'
 * @param function func A callback function on success
 */
TC.ajax.send = function(url, type, data, dataType, func) {
	$.ajax({
		url: url,
		type: type,
		dataType: dataType,
		data: data,
		success: function(object, status) {
			if (object.code && object.redirect)
				window.location = object.redirect;
			
			if (object.code && object.dialog) {
				var defaultDialog = $("#jsDefaultDialog");
				
				defaultDialog.find('p').text(object.dialog.body);
				defaultDialog.find('span.ok').text(object.dialog.button_text);
				
				var dialogParams = {
					resizable: false,
					height: 150,
					width: 400,
					modal: true,
					overlay: {
						backgroundColor: '#4e8394',
						opacity: 0.5
					},
					title: object.dialog.title,
					buttons: {}
				};
				
				dialogParams.buttons[object.dialog.button_text] = 
					function() { defaultDialog.dialog("close"); };
				
				defaultDialog.dialog(dialogParams);
			}
			
			if (object.errors && ! $.isArray(object.errors)) {
				if (console)
					console.log(object.errors);
				else
					alert(object.errors);
				
				var object = {code: 'error', errors: [{message: TC.string.stripTags(XMLHttpRequest.responseText)}]};
				func.apply(this, [object]);
			}
			else
			{
				func.apply(this, [object]);
			}
		},
		error: function(XMLHttpRequest, textStatus, errorThrown) {
			var object = {code: 'error', errors: [{message: TC.string.stripTags(XMLHttpRequest.responseText)}]};
			func.apply(this, [object]);
		}
	});
};

/**
 * TC.ajax.getJson
 *
 * Perform an POST Ajax call
 *
 * @param string url The URL to call with Ajax
 * @param string type Either POST or GET
 * @param mixed data The data sent to the url
 * @param string dataType e.g. 'json'
 * @param function func A callback function on success
 */
TC.ajax.getJson = function(url, data, func) {
	TC.ajax.send(url, 'post', data, 'json', func);
};

/**
 * TC.ajax.sendFile
 * 
 * Perform an Ajax file upload
 */
TC.ajax.sendFile = function(url, fileElementId, dataType, func) {
	$.ajaxFileUpload({
		url: url,
		secureuri: false,
		fileElementId: fileElementId,
		dataType: dataType,
		success: function(object, status) {
			func.apply(this, [object]);
		},
		error: function(XMLHttpRequest, textStatus, errorThrown) {
			var object = {code: 'error', errors: TC.string.stripTags(XMLHttpRequest.responseText)};
			func.apply(this, [object]);
		}
	});
};

/**
 * TC.errors.add
 * 
 * Add an error to the HTML list of errors
 */
TC.errors.add = function(errorContainer, errors) {
	if(errorContainer.children().length == 0) {
		errorContainer.append('<ul></ul>');
	}
	
	var errorMessageIsUndefined = false;
	for (var i = 0; i < errors.length; i++) {
		if (typeof errors[i].message != 'undefined') {
			TC.html.addLineToList(errorContainer.find('ul'), errors[i].message);
		}
		else {
			errorMessageIsUndefined = true;
		}
	}
	
	if (errorMessageIsUndefined) {
		TC.html.addLineToList(errorContainer.find('ul'), "An uncaught error occurred.");
	}
	
	errorContainer.show();
};

/**
 * TC.errors.clear
 * 
 * Clears all the errors in the HTML list of errors
 */
TC.errors.clear = function(errorContainer) {
	errorContainer.empty();
};

/**
 * populateCountrySelect
 *
 * Populate a select (HTML drop down list) with a content array
 * @param object select The HTML select to be populated
 * @param array content An associative array that contains the (key, value) that populates the HTML select
 */
TC.html.populateCountrySelect = function(select, content) {
	$.each(content, function() {
		TC.html.addOptionToSelect(select, this['code'], this['name']);
	});
};

/**
 * populateSelect
 *
 * Populate a select (HTML drop down list) with a content array
 * @param object select The HTML select to be populated
 * @param array content An associative array that contains the (key, value) that populates the HTML select
 */
TC.html.populateSelect = function(select, content) {
	for (var key in content) {
		TC.html.addOptionToSelect(select, key, content[key]);
	}
};

/**
 * emptySelect
 *
 * Clear all items from an HTML select and add a default text with an empty string
 * @param object select
 * @param string defaultText
 */
TC.html.emptySelect = function(select, defaultText) {
	select.empty();
	TC.html.addOptionToSelect(select, '', defaultText);
}

/**
 * addOptionToSelect
 *
 * Add an item to an HTML select
 * @param object select
 * @param string value
 * @param string text
 */
TC.html.addOptionToSelect = function(select, value, text) {
	select.append("<option value='" + value + "'>" + text + "</option>");
};

/**
 * addLineToList
 *
 * Add an line to a HTML ul list
 * @param object ul
 * @param string text
 */
TC.html.addLineToList = function(ul, text) {
	ul.append('<li>' + text + '</li>');
};

TC.debug.printObject = function(theObj) {
	var str = "<ul>\n";
	if(theObj.constructor == Array || theObj.constructor == Object) {
		for(var p in theObj) {
			if(theObj[p].constructor == Array || theObj[p].constructor == Object) {
				str += "<li>[" + p + "] => " + typeof(theObj) + "</li>\n";
				str += "<ul>\n";
				str += TC.debug.printObject(theObj[p]);
				str += "</ul>\n";
			} else {
				str += "<li>[" + p + "] => " + theObj[p] + "</li>\n";
			}
		}
		str += "</ul>\n";
		return str;
	}
};

TC.debug.alertObject = function(theObj) {
	alert(TC.debug.printObject(theObj));
};

TC.data.load = function() {
	TC.data.loadedData = TC.string.jsonDecode($('#publicParams').val());
};

TC.data.get = function(index) {
	if (typeof eval('TC.data.loadedData.' + index) != 'undefined') {
		return eval('TC.data.loadedData.' + index);
	}
	
	return false;
};

function dump(val) {
	if ( ! $('#dump').length) {
		$('body').prepend('<div id="dump" style="position:fixed;z-index:100000;bottom:0;left:50px;opacity:0.7;width:100%;height:85px;background:#000;"><div class="close" style="cursor:pointer; font-weight:bold;color:white; float: right;">X </div><ul></ul></div>').show();
		
		$('#dump .close').click(function() {
			$('#dump').hide();
		});
	}
	
	$('#dump ul').append('<li style="color:white;">' + val + '</li>');
	return val;
}

