var MESSAGES_DURATION = 8000; // in milliseconds

function initialize() {
	initializeCalendars();
	initializeFocus();
	initializeCancel();
	initializeMessages();
	initializeRemoteForms();
	initializeConfirms();
	initializeClosePictures();
//	initializePrintableContent();
} // initialize

function initializeClosePictures() {
	$$('img.close').each(function(node) {
		node.observe("mouseover", function(e) {
			node.src = node.src.replace('.png', '-hover.png');
		});
		
		node.observe("mouseout", function(e) {
			node.src = node.src.replace('-hover.png', '.png');
		});		
	});
} // initializeClosePictures

function initializeCancel() {
	$$('img.cancel').each(function(node) {
		node.observe('mouseover', function(e) {
			node.src = "/images/cancel_hover.png";
		});
		
		node.observe('mouseout', function(e) {
			node.src = "/images/cancel.png";
		});

		node.observe('click', function(e) {
			var input = node.previous("input[type='text']");
			if(input) {
				input.clear();
				input.focus();
			}
		});
	});	
} // initializeCancel

function initializeCalendars() {
	$$('img.calendar').each(function(node) {
		node.observe('click', function(e) {
			c = Calendar.getInstance(e);
			if(c) c.display();
		});
	});	
} // initializeCalendars

function initializeCompaniesSelect(field_name) {
	initializeFirmsSelect(field_name, "companies");
} // initializeCompaniesAutoCompleter

function initializeConfirms() {
	$$('form.confirm').each(function(node) {
		node.observe('submit', function(e) {
			if(!confirm(I18n.t('confirm_generic_suppression')))
				e.stop();
		});
	});
} // initializeConfirms

function initializeCustomersSelect(field_name) {
	initializeFirmsSelect(field_name, "customers");
} // initializeCustomersAutoCompleter

function initializeProvidersSelect(field_name) {
	initializeFirmsSelect(field_name, "providers");
} // initializeProvidersAutoCompleter

function initializeFirmsSelect(field_name, type) {
	var select = $(field_name);
	var loader = retrieveLoader();
	new Form.Element.Observer(
	  'company_name',
	  1,  // 1000 milliseconds
	  function(element, value){			
			new Ajax.Request("/bo/" + type + "/filter_by_name_options", {
				parameters: { 
					"authenticity_token": getAuthenticityToken(),
					"company[name]": value
				},
				onCreate: function(transport) {					
					loader.show();
				},
				onSuccess: function(transport) {
					select.update(transport.responseText);
				},
				onComplete: function(transport) {
					loader.hide();
				}
			});
	  }	
	);	
} // initializeFirmsSelect

function initializeFocus() {
	$$('input.focus').each(function(node) {
		node.focus();
	});
} // initializeFocus

function addMessageFromJSON(object) {
	if(object) {
		var messages = getMessagesContainer();		
		var message = messageAlreadyExist(object.message);
		
		if(! message) {
			message = new Element("div", { "class": object.klass }).update(object.message);
			messages.insert({bottom: message});
		}
		
		setTimeout(function() {
			new Effect.Highlight(message);
		}, 300);
	}
} // addMessageFromJSON

function messageAlreadyExist(text) {
	var messages = getMessages();
	var m = null;
	
	messages.each(function(message) {
		if(message.innerHTML == text) {
			m = message;
			return;
		}
	});
	return m;
} // messageAlreadyExist

function initializePrintableContent() {
	$$('a.printable').each(function(node) {
		node.observe('click', function(e) {
			window.open(node.href);
			e.stop();
		});
	});
} // initializePrintableContent

function getMessagesContainer() {
	return $("messages");
} // getMessagesContainer

function getMessages() {
	return $$('#messages div');
} // getMessages

function initializeMessages() {
	new PeriodicalExecuter(markAndPopMessages, 3);	
} // initializeMessages

function cleanFormErrors(form) {
	form.select('.error').each(function(node) {
		'P' == node.nodeName ? node.remove() : node.removeClassName('error');
	});
} // cleanFormErrors

function submitRemoteForms(e, form, options) {
	// stop observing to avoid multiple requests
	form.stopObserving('submit');
	// remove each error
	cleanFormErrors(form);
	
	var loader 	= retrieveLoader();
	var values  = form.serialize(true);

	enableLoader();
	form.disable();
	new Ajax.Request(form.action, {
		parameters: values,
		onFailure: function(transport) {
			var object = transport.responseJSON;
			if(object && object.basename && object.errors) {
				object.errors.each(function(error) {
					var field = $(object.basename + '_' + error.first());
					if(field) {
						field.addClassName('error');
						var message = new Element('p', { 'class': 'error' }).update(error.last());
						field.insert({ after: message });
					} else {
						addMessageFromJSON({ 'klass': 'error', 'message': I18n.t(error.first()) + " " + error.last() });
					}
					
				});
			}			
		},
		
		onSuccess: function(transport) {
			callbacks = options.get('successCallbacks');
			if(callbacks) {
				if("function" == typeof callbacks) {
					callbacks(transport);
				} else {
					callbacks.each(function(callback) {					
						if("function" == typeof callback) {
							callback(transport);
						}
					});
				}
			}
			if(options.get('resetOnSuccess'))
				form.reset();
		},
		
		onComplete: function(transport) {
			addMessageFromJSON(transport.responseJSON);
			// re register event
			registerRemoteFormSubmit(form, options);
			disableLoader();
			form.enable();
			if(options.get('focus'))
				form.focusFirstElement();
		}
	});
	// prevent propagation
	e.stop();	
} // submitRemoteForms

function registerRemoteFormSubmit(form, options) {
	form.observe('submit', function(e) { submitRemoteForms(e, form, options) });
} // registerRemoteFormSubmit

function initializeRemoteForms() {
	$$('form.remote').each(function(form) {
		registerRemoteFormSubmit(form, new Hash({ focus: true }));
	});
	
	$$('form.remote_without_focus').each(function(form) {
		registerRemoteFormSubmit(form, new Hash({ focus: false }));
	});			
} // initializeRemoteForms

/*
 * Use a timestamp to mark and pop messages.
 * Set a timestamp to the div if it has'nt yet. Otherwise, calcule the difference
 * between the current timestamp and the attribute. If the diff is greater or equal
 * than the defined duration, destroy the message.
 */
function markAndPopMessages() {
	getMessages().each(function(node) {
		var timestamp_attribute = node.readAttribute("timestamp");
		if(timestamp_attribute) {
			if((timestamp() - timestamp_attribute) >= MESSAGES_DURATION) {
				new Effect.Fade(node, {
					afterFinish: function(e) {
						node.remove();
					}
				});
			}			
		} else
			node.writeAttribute("timestamp", timestamp());
	});
} // markAndPopMessages

function timestamp() {
	return new Date().getTime();
} // timestamp

function retrieveLoader() {
	return $('loader') || function() { 
		var element = new Element("img", { 
			"id": "loader", 
			"src": "/images/loader.gif"
		});
		element.hide();
		$('container').insert({'top': element});
		return element;
	}();	
} // retrieveLoader

function enableLoader(loader) {
	loader = loader || retrieveLoader();
	loader.show();
} // enableLoader

function disableLoader(loader) {
	loader = loader || retrieveLoader();
	loader.hide();
} // retrieveLoader

function toggleLoader() {
	var loader = retrieveLoader();
	loader.visible() ? disableLoader(loader) : enableLoader(loader);
} // toggleLoader

function getAuthenticityToken() {
	return $('token').down().value;
} // getAuthenticityToken

Event.observe(document, 'dom:loaded', initialize);