/**
 * Javascript for communicating with components.
 *
 * @see ComponentUpdate
 */

/**
 *	Component communication class.
 */
function Component(element) {

	/**
	 * @var element component root element
	 */
	this.element = jQuery(element);

	/**
	 * @var string component id
	 */
	this.id = this.element.attr("id");

	/**
	 * Update the elements in the component.
	 *
	 * @param data array
	 */
	this.update = function(data) {
		if ('redraw' in data) {
			this.redraw(data['redraw']);
		} else {
			this.update_html(data['html']);
			this.update_form_values(data['values']);
		}
	}

	/**
	 * Replace content of entire element.
	 *
	 * @param html
	 */
	this.redraw = function(html) {
		if (element.html() == html)
			return;
		element.fadeOut(400, function(){jQuery(this).html(html).fadeIn()});
	}

	/**
	 *
	 * @param html array
	 */
	this.update_html = function(html) {
		for (var target_class_name in html) {
			var element = this.element.find("." + target_class_name);
			if (element != undefined)
				this.update_element(element, html[target_class_name]);
		}
	}

	/**
	 * Update the form fields in the component
	 *
	 * @param values array
	 */
	this.update_form_values = function(values) {
		for (var target_id in values) {
			var element = this.element.find("#" + target_id);
			if (element != undefined)
				this.update_form_value(element, values[target_id]);
		}
	}

	/**
	 * Update an element in the component. The html content of the element will be replaced.
	 *
	 * @param element element
	 * @param value string
	 */
	this.update_element = function(element, value) {
		var element_to_update = jQuery(element);

		// Do not update element if value is the same.
		// This will prevent the fade effect from showing needlessly.
		if (element_to_update.html() == value)
			return;
		
		// Update the element
		if (element_to_update.hasClass('visual_attraction'))
			// with an effect to attract the user
			element_to_update.fadeOut(400, function(){jQuery(this).html(value).fadeIn()});
		else
			// Without an effect
			element_to_update.html(value);
	}

	/**
	 * Update the value for a form field in the component.
	 *
	 * @param element element
	 * @param value mixed
	 */
	this.update_form_value = function(element, value) {
		var element_to_update = jQuery(element);

		// Do not update element if value is the same.
		if (element_to_update.val() == value)
			return;

		jQuery(element).val(value);
	}
}

/**
 * Component repository
 */
Component.repository = {};

/**
 * Register a component in the component repository.
 *
 * Class function
 * @param element
 * @return Component
 */
Component.register = function (element) {
	var component = new Component(element);
	Component.repository[component.id] = component;
	return component;
}

/**
 * Find a component.
 *
 * Class function
 * @param id Component ID
 * @return Component
 */
Component.find = function (id) {
	return Component.repository[id];
}

/**
 * Update ALL components.
 *
 * Class function
 * @param update_data array of data for all components
 */
Component.update = function (update_data) {

	for (var component_id in update_data) {

		var component = Component.find(component_id);

		if (component != undefined) {
			component.update(update_data[component_id]);
		}
	}
}

/**
 * Register all components on the page that have an id
 */
jQuery(function() {
	jQuery(".sig_component").each(function(){
		var component = jQuery(this);
		var component_id = component.attr("id");
		if (component_id != undefined && component_id != "")
			Component.register(jQuery(this));
	});
});

/**
 * Debugger request
 */
//Component.debugUpdateRequest = function() {
//	jQuery.ajax({
//		url:"/catalogue",
//		data: {action: "test"},
//		type: "post",
//		success: function(data, textStatus, jqXHR) {
//			var update_data = eval(data);
//			Component.update(update_data);
//		}
//	})
//}

/**
* Connect debugger.
*/
//jQuery(function() {
//	jQuery("#component_debugger_button").click(function(event) {
//		Component.debugUpdateRequest();
//		event.preventDefault();
//	})
//})
