// Namespace object for current site
C_tfo_lib = function(v_site_url){

	///////////////////////////////
	// Properties
	this.site_url = null;
	
	// Namespace components
	this.widgets = {};
	this.stddialogs = {
		"alert"		: null,
		"error"		: null,
		"confirm"	: null
	}
	
	///////////////////////////////
	// Private methods
	
	
	// Constructor function
	var init = function(v_site_url){
		
		// Params
		this.site_url = (v_site_url || '');
		
		// Init components
		this.stddialogs = {
			"alert"		: new C_widget_dialog('tfo_stddlg_alert', this, {}),
			"error"		: new C_widget_dialog('tfo_stddlg_error', this, {}),
			"confirm"	: new C_widget_dialog('tfo_stddlg_confirm', this, {})	
		}
		
		return this;
	}.bind(this) // init()
	
	///////////////////////////////
	// Public methods
	
	// Init page
	this.initPage = function(){
		
		// Externalise links
		this.externaliseLinks(document);
		
		return this;
	} // this.initPage()

	// Ajaxify contact form
	this.convertContactForm = function(o_form){
		if (o_form){
			
			var $this = $(o_form);
			$this.attr('autocomplete', 'off');
		
			// Capture the form submit event
			$this.submit(function(e){
				e.preventDefault();
			
				// Update UI
				var o_loading = $('<div/>').addClass('loading').attr('id', 'loading-notice').append(
						$('<div/>').addClass('image')
					).append(
						$('<div/>').addClass('message ').html('Sending your message..')
					);
				$(this).hide().after(o_loading.show());

				// Post form to server
				$.ajax({
					type		: "POST",
					url			: $(this).attr('action'),
					cache		: false,
					data		: $.param($(this).find(':input[name]')),
					dataType	: "json",
					success		: function(o_data){

						// Check for errors and alert user if failed
						if (o_data.error.length == 0){
							
							// Show the message
							$('#loading-notice').html(o_data.message);
							
							// Set timer to clear message and reset form
							setTimeout(function(){
								$('#loading-notice').remove();
								$this.fadeIn();
								$this.find(':input').each(function(v_index){
									$(this).removeClass('failed');
								});
								$('#' + $this.attr('id') + '-error').hide();
								$(':input', $this)
									.not(':button, :submit, :reset, :hidden')
									.val('')
									.removeAttr('checked')
									.removeAttr('selected');
							}, 3000);
								
						} else {
					
							// Update UI to show errors						
							if (!$.isEmptyObject(o_data.failedfields)){
						
								// Remove previous validation errors and add new ones
								$this.find(':input').each(function(v_index){
									
									// Remove previous validation
									$(this).removeClass('failed');
									
									// Does this field have an error message?
									var v_fieldname = $(this).attr('id');
									for (var i in o_data.failedfields){
					
										if (i == v_fieldname){
										
											// Highlight the failed field
											var o_fld = $this.find('#' + v_fieldname);
											o_fld.addClass('failed').attr('title', o_data.failedfields[i]);
											
											// Show general error
											$('#' + $this.attr('id') + '-error').html('The form is incomplete.<br />' +
												'Required fields are highlighted.').show();
												
											// Show form and focus first failed field
											$this.show(); 
											$('#loading-notice').remove();
											if ($this.find('input.failed').length > 0){
												$this.find('input.failed').get(0).focus();
											}
												
										}
									}
									
								});
	
							} else {
							
								// General failure				
								$('#' + $this.attr('id') + '-error').html(o_data.error).show();
								$this.show(); 									
								$('#loading-notice').remove();
							
							}
						
						}
					},
					error		: function(o_ajax, v_status, o_error){
						_tfo.showError("An error occurred sending your request (" + 
							o_ajax.statusText + ").  Please refresh the page and try again.");
					}
				});
			
				return false;
			});
		
		}
		return this;
	} // this.convertContactForm()
	
	// Unescape HTML entities via jQuery
	this.unescapeHTML = function(v_buf){
		return $('<div/>').text(v_buf).html();
	} // this.unescapeHTML()
	
	// Make external links, external (XHTML doesnt allow target="_blank")
	// 		o_node: root element to start searching from
	this.externaliseLinks = function(o_node){
		var o_wnode = (o_node ? $(o_node) : $(document));
		o_wnode.find('.external').attr('target', '_blank');
		return this;
	}
	
	// Style form components same as jQuery UI theme
	this.themeUI = function(o_root_node){
		
		// Use document if no root gtiven
		if (!o_root_node){
			o_root_node = $(document).eq(0);
		} else {
			o_root_node = $(o_root_node);
		}
		
		// Add priority to form buttons
		o_root_node.find('button[type="submit"]').attr('priority', 'primary');
		o_root_node.find('button[type="reset"]').attr('priority', 'secondary');
		
		// Theme form buttons
		o_root_node.find('button')
			.addClass('ui-button ui-widget ui-state-default ui-corner-all ui-priority-secondary')
			.hover(
				function(){$(this).addClass("ui-state-hover");},
				function(){$(this).removeClass("ui-state-hover");}
			);
		o_root_node.find('button[priority="primary"]')
			.removeClass('ui-priority-secondary')
			.addClass('ui-priority-primary');
		
		// Theme form elements to match theme
		o_root_node.find('input, select, textarea')
			.addClass('tfo-form-input ui-corner-all')
			.focus(function(){$(this).addClass("ui-state-focus");})
			.blur(function(){$(this).removeClass("ui-state-focus");});
		
		// Theme error elements
		//o_root_node.find('.error').addClass('ui-state-error ui-corner-all');
		
		return this;
	} // this.themeUI()
	
	// Show an alert dialog
	this.showAlert = function(v_msg, v_title){
		this.stddialogs.alert.showInfo(
			(v_title ? v_title : 'Alert'),
			(v_msg || '')
		);
		return this;
	} // this.showAlert()
	
	// Show a confirm dialog
	// Returns boolean to callback handler
	this.showConfirm = function(v_msg, v_title, v_handler){		
		this.stddialogs.confirm.showConfirm(
			(v_title ? v_title : 'Confirm'),
			(v_msg || ''),
			v_handler
		);		
		return this;
	} // this.showConfirm()
	
	// Show an error dialog
	// Bind to 'this' incase this function is assigned by reference
	this.showError = function(v_msg, v_title){
		this.stddialogs.error.showError(
			(v_title ? v_title : 'Error'),
			(v_msg || '')
		);
		return this;
	}.bind(this) // this.showError()
	
	// Unescape HTML entities via jQuery
	this.escapeHTML = function(v_buf){
		return $('<div/>').text(v_buf).html();
	} // this.unescapeHTML()
	
	// Get the length of an assoc array
	this.getAssocArrayLength = function(arr){
	    var l = 0;
	    for (var i in arr) {
	        if (Object.prototype.hasOwnProperty.call(arr, i)){l++;}
	      }
	    return l;
	} // this.getAssocArrayLength()
	
	///////////////////////////////
	// Call constructor
	return init(v_site_url);
	
} // C_tfo_lib()

//////////////////////////////////////////////////////////////////////////////////
// Scope bind function - allows binding of external objects as "this" in functions
if (!Function.prototype.bind){
	Function.prototype.bind = function(obj) {
		var method = this,
		temp = function() {
			return method.apply(obj, arguments);
		};
		return temp;
	}
}

