/****************************************************
 * @type dqValidate jquery plugin
 * @about Плагин подсветки валидации
 * @param json data - от php валидатора
 * 		data.error_2_fields - json [{поле:[ошибки]}, ...]
 * 		data.global_errors - array [ошибка, ...]
 * @param json conf - дополнительные настройки
 * @author Coroliov Oleg aka ruscon
 * **************************************************
 * @version 0.1
 * @date 2010-07-20
 * Основная логика плагина
 * 
 * @version 0.2
 * @date 2010-08-05
 * Скролин до ошибок не привязанных к полям
 * Скролинг до первого по порядку инпута в форме, если нет не привязанных ошибок
 * Поправлена подсветка select для плагина
 * 
 * @version 0.3
 * @date 2010-09-22
 * Новый передаваемый массив actions - используется для выполнения глобальных действий
 * 		Доспупные варианты:
 * 			string redirect - ссылка, куда редиректить 
 * **************************************************
 * @about bubble plugin
 * в файле бабла сделаны изменения
 * 1) Выставлен путь до изображений
 * 2) Было "popup_obj.appendTo(tag_obj);"
 * 		Сделал "popup_obj.appendTo('body');"
 * 		Т.к. appendTo нельзя применять к input
 * 3) Было в двух местах "if (_.popups[i]) clearTimeout(_.popups[i]);"
 * 		Сделал "if (_.popups[i]) clearTimeout(parseInt(_.popups[i]));"
 * ************************************************** 
 */
(function($) {
	var 
	// plugin config
	config = {			
		theme : 'dq-validate',		// префикс для классов
		global_errors_to : '.dq-validate-errors', // селектор для вывода не прикреплённых ошибок
		bubbleColor : 'blue', 		// azure|blue|green|gray|orange|violet|yellow
		bubbleAlign : 'left', 		// center|left|right
		tailAlign: 'left', 			// center|left|right
		pre_show_duration : 5000    // длительность предварительного показа ошибок 
	},
	// Внутренние переменные
	_vars = {
		have_error_2_fields : 0,
		have_global_errors : 0,
		have_actions : 0,
		focused_on_first_field : 0
	},
	// jquery object
	form = null,
	// Установка конфига
	_init = function(conf)
	{
		_destroy();

		if(typeof conf !== 'object') conf = {};
		config = $.extend(config, conf);
	},
	// Установка конфига bubble plugin
	_init_bubble_config = function(value)
	{
		return {
			innerHtml: value, 
			openingVelocity: 250,
			distanceFromTarget: 10,
			bubbleAlign: config.bubbleAlign,
			tailAlign: config.tailAlign,
			color: config.bubbleColor,
			contentStyle: 'font-size:11px;',
			showOnMouseOver: false,
			zIndex : 100
		}
	},
	// Очистка работы плагина
	_destroy = function()
	{
		$("*", form).removeClass(config.theme+'-error').unbind('showBubblePopupHandler');
		$(config.global_errors_to).html('');
	},
	// Установка скролинга
	_setScrollTo = function(obj, ms)
	{
		if(!obj.size()) return false;
		
		if(!ms) ms = 1;
		$.scrollTo(obj, ms);
		$.scrollTo('-=100', 0);
	},
	// Обработка ошибок, привязанных к полям
	_setErrors2Fields = function(errors)
	{
		if(!$.isPlainObject(errors)) return false;
		_vars.have_error_2_fields = true;

		$.each(errors, function(key, value){
			_set2Field(key, value);
		});

		// Если не поставлены глобальные ошибки
		if(!_vars.have_global_errors) _setScrollTo($('.'+config.theme+'-error', form).first());
	},
	// Обработка действий
	_setActions = function(actions)
	{		
		if(!actions) return false;
		_vars.have_actions = true;

		if(actions.redirect){
			window.location.href = actions.redirect;
			return true;
		}
	},	
	// Обработка глобальных ошибок
	_setGlobalErrors = function(errors)
	{		
		if(!errors) return false;
		_vars.have_global_errors = true;

		var err_obj = $(config.global_errors_to);
		if(!err_obj.size()) return false;

		var html = '';
		if($.isArray(errors)){
			$.each(errors, function(key, value){	
				html += '<div>'+value+'</div>';		
			});
		} else {
			html += '<div>'+errors+'</div>';
		}
		
		err_obj.append(html);

		_setScrollTo(err_obj);
	},
	// Обработка ошибки, привязанной к полю
	_set2Field = function(key, value)
	{
		var field = $('input[name$=\['+key+'\]], select[name$=\['+key+'\]], textarea[name$=\['+key+'\]]', form);
		if(!field.size()) return;

		switch(field.attr('tagName').toLowerCase()){
			case 'select' :
				var new_field = field.next()
				// Если плагин для select
				if(new_field.hasClass('styledSelect')){
					field = new_field;					
					_set_select_events(field, value);
				} else{
					_set_default_events(field, value);
				}
				break;
			case 'input' :
				switch(field.attr('type').toLowerCase()){
					// Плагин для checkbox
					case 'checkbox' :						
						var new_field = field.next('span');
						if(new_field.hasClass('dq-checkbox')){
							field = new_field;
							_set_checkbox_events(field, value);
						} else{
							_set_default_events(field, value);
						}
						break;
					// Плагин для radiobox
					case 'radio' :						
						var new_field = field.next('span');
						if(new_field.hasClass('dq-radiobox')){
							field = new_field;
							_set_radiobox_events(field, value);
						} else{
							_set_default_events(field, value);
						}
						break;
					default :
						_set_default_events(field, value);
						break;
				}
			default :
				_set_default_events(field, value);
				break;
		}
	},

	_pre_show_errors = function(field){
		field.ShowBubblePopup();
		setTimeout(function(){field.HideBubblePopup();}, config.pre_show_duration);
	},

	// Логика для обычных полей
	_set_default_events = function(field, value)
	{
		field.addClass(config.theme+'-error').SetBubblePopup(_init_bubble_config(value[0]));
		_pre_show_errors(field);

		field.mouseover(function(){
			$(this).ShowBubblePopup();
		}).mouseout(function(){ 
			$(this).HideBubblePopup(); 
		}).focus(function(){
			$(this).unbind('showBubblePopupHandler').removeClass(config.theme+'-error').HideBubblePopup();
		});

		if (_vars.focused_on_first_field != 1){
			field[0].focus();
			_vars.focused_on_first_field = 1;
		}
	},

	// Логика для плагина select
	_set_select_events = function(field, value)
	{
		$('li', field).addClass(config.theme+'-error');
		field.SetBubblePopup(_init_bubble_config(value[0]));
		_pre_show_errors(field);

		field.mouseover(function(){
			$(this).ShowBubblePopup();
		}).mouseout(function(){ 
			$(this).HideBubblePopup(); 
		});
		$('ul', field).click(function(){
			field.unbind('showBubblePopupHandler').removeClass(config.theme+'-error').HideBubblePopup();
		});
	},
	// Логика для плагина checkbox
	_set_checkbox_events = function(field, value)
	{
		field.addClass(config.theme+'-error').SetBubblePopup(_init_bubble_config(value[0]));
		_pre_show_errors(field);

		field.mouseover(function(){
			$(this).ShowBubblePopup();
		}).mouseout(function(){
			$(this).HideBubblePopup();
		}).click(function(){
			field.unbind('showBubblePopupHandler').removeClass(config.theme+'-error').HideBubblePopup();
		});
	},
	// Логика для плагина radiobox
	_set_radiobox_events = function(field, value)
	{
		field.addClass(config.theme+'-error').SetBubblePopup(_init_bubble_config(value[0]));
		_pre_show_errors(field);
		
		field.mouseover(function(){
			$(this).ShowBubblePopup();
		}).mouseout(function(){ 
			$(this).HideBubblePopup(); 
		}).click(function(){
			field.unbind('showBubblePopupHandler').removeClass(config.theme+'-error').HideBubblePopup();
		});
	};

	$.dqValidate = function(form_selector, data, conf)
	{
		form = $(form_selector);
		if(form.size() != 1) return;

		_init(conf);
		_setActions(data.actions);
		_setErrors2Fields(data.error_2_fields);
		_setGlobalErrors(data.global_errors);
		//_setScroll();
	};
})(jQuery);
