/**
 *	Estudo
 *	
 *	
 *	@param $settings object
 *
 */
(function($){
	$.fn.estudo = function(settings) {
		$form = this;
	/**
	 *	Settings
	 *	estende os parametros padrões do plugin
	 *	@object
	 */
		var settings = jQuery.extend({}, $.fn.estudo.defaults, settings);
	/**
	 *	Runtime
	 *	objeto memoria do estado de execução
	 *	@object
	 */
		var runtime = new Object();
	/**
	 *	scrollable
	 *
	 *
	 */
		function scrollable() {
			itsSettings = jQuery.extend({}, settings.scrollable, {
				onBeforeSeek : function(event, i){
					scrollable_markPage(i);
					scrollable_observePage(i);
				}
			});
			runtime.scrollable = jQuery(settings.wizard).scrollable(itsSettings);
		};
	/**
	 *	scrollable_markPage
	 *
	 *
	 */
		function scrollable_markPage(i) {
			jQuery("li", settings.paginate).find('a').removeClass('current').end().eq(i).find('a').addClass('current');
		 };
	/**
	 *	scrollable_observePage
	 *
	 *
	 */
		function scrollable_observePage(i) {
			i = parseInt(i) + 1;			
			// primeira pagina
			if ( i == 1 ) {
				observeButton_prev('hide');
				observeButton_submit('hide');
				observeButton_next('show');
			}
			// ultima pagina
			else if ( i == runtime.scrollable.getItems().size() ) {
				observeButton_next('hide');
				observeButton_prev('show');
				observeButton_submit('show');
			}
			// outras páginas
			else {
				observeButton_submit('hide');
				observeButton_prev('show');
				observeButton_next('show');
			}
		 };
	/**
	 *	scrollable_goToPage
	 *	abre página passada como parametro
	 *
	 *	@param $page int
	 *	@return void
	 */
		function scrollable_goToPage(page) {
			i = parseInt(page) - 1;
			if ( i < 0 ) return false;
			if ( runtime.scrollable.getPageIndex() != i ) runtime.scrollable.setPage(i);
		};
	/**
	 *	scrollable_preventTab
	 *	previne mudança de ultimo campo de cada formulário por tab
	 *
	 */ 
		function scrollable_preventTab() {
			wizard_getInstance().find(".page").find("input:last").keydown(function(e){
				if ( e.keyCode == 9 ) {
					runtime.scrollable.next();
					e.preventDefault();
				}
			});
		};
	
	/**
	 *
	 *
	 *
	 */ 
		function observeButton_submit(e) {
			if ( typeof e == "undefined" ) return;
			if ( e == 'show' )
				wizard_getInstance().find(settings.submit).show();
			else if ( e == 'hide' )
				wizard_getInstance().find(settings.submit).hide();
		};
	/**
	 *
	 *
	 *
	 */ 
		function observeButton_next(e) {
			if ( typeof e == "undefined" ) return;
			if ( e == 'show' )
				wizard_getInstance().find(settings.next).show();
			else if ( e == 'hide' )
				wizard_getInstance().find(settings.next).hide();
		};
	/**
	 *
	 *
	 *
	 */ 
		function observeButton_prev(e) {
			if ( typeof e == "undefined" ) return;
			if ( e == 'show' )
				wizard_getInstance().find(settings.prev).removeAttr("disabled");
			else if ( e == 'hide' )
				wizard_getInstance().find(settings.prev).attr("disabled",true);
		};
	/**
	 *	observeFocus
	 *	observa focus de elementos do formulário, adiciona e remove classe
	 *
	 *	@return void
	 */
		function observeFocus() {
			jQuery("input[type=text],textarea,select", $form).focus(function(){
				jQuery(this).addClass('focus');
			}).blur(function(){
				jQuery(this).removeClass('focus');
			});
		};
	/**
	 *	observeLoading
	 *	observa focus de elementos do formulário, adiciona e remove classe
	 *
	 *	@return void
	 */
		function observeLoading(e) {
			if ( typeof e == "undefined" ) return;
			$loading = loading_getInstance();
			if ( e == 'show' )
				$loading.fadeIn();
			else if ( e == 'hide' )
				$loading.fadeOut();
		};
	/**
	 *	observeLoading
	 *	observa focus de elementos do formulário, adiciona e remove classe
	 *
	 *	@return void
	 */
		function loading_getInstance() {
			if ( typeof runtime.loading == "undefined" )
				runtime.loading = jQuery(settings.loading).insertAfter(settings.submit);
			return runtime.loading;
		};
	/**
	 *	wizard_getInstance
	 *	cria ou recupera instancia do wizard
	 *
	 *	@return object jQuery
	 */ 
		function wizard_getInstance() {
			if ( typeof runtime.wizard == "undefined" )
				runtime.wizard = jQuery(settings.wizard);
			return runtime.wizard;
		};
	/**
	 *	wizard_getInstance
	 *	cria ou recupera instancia do wizard
	 *
	 *	@return object jQuery
	 */ 
		function bindPaginate() {
			$paginate = jQuery(settings.paginate);
			$paginate.find("li").each(function(){
				$li = jQuery(this);
				var index = parseInt($li.index());
				$li.find("a").bind('click',function(e){
					e.preventDefault();
					scrollable_goToPage(index + 1);
				});
			});
		};
	/**
	 *	maskInput
	 *	define mascara de campos do formulario
	 *
	 *	@return void
	 */
		function maskInput() {
			for ( field in settings.mask ) $( "#" + field ).setMask(settings.mask[field]);		
		};
	/**
	 *	validate
	 *	valida formulário ao ser submetido
	 *
	 *	@return void
	 */
		function validate() {
			itsSettings = jQuery.extend({}, settings.validate, {
				submitHandler: function(form){
					$.ajax({
						type : "POST",
						url : $form.attr('action'),
						data : $form.serialize(),
						cache : false,
						dataType : "json",
						timeout : 5000,
						beforeSend : function(){
							observeLoading('show');
						},
						error : function(){
							message(settings.validate.messages.fail);
						},
						success : function(data){
							if ( !parseInt(data.status) ) {
								message(data.message);
							}
							else {
								message(data.message,'success');
								runtime.wizard.fadeOut().remove();
							}
						},
						complete : function(){
							observeLoading('hide');
						}
					});
					return false;
				},
				showErrors: function(errors) {	
					if ( !isEmpty(errors) )
						message(settings.validate.messages.err);
					this.defaultShowErrors();
				},
				errorPlacement: function(error, element){
					if ( element.attr("name") == "tel_ddd" || element.attr("name") == "tel_nro" )
						error.insertAfter("#tel_nro");
					else if ( element.attr("name") == "fax_ddd" || element.attr("name") == "fax_nro" )
						error.insertAfter("#fax_nro");
					else if ( element.attr("name") == "cel_ddd" || element.attr("name") == "cel_nro" )
						error.insertAfter("#cel_nro");
					else
						error.insertAfter(element);
				}
			});
			$form.validate(itsSettings);
		};
	/**
	 *	message
	 *	mostra mensagem sucesso/erro no formulário
	 *
	 *	@param $string string
	 *	@param $type string
	 *	@return void
	 */
		function message(string, type) {		
			if ( typeof string == "undefined" ) return;
			$message = message_getInstance();
			if ( typeof type == "undefined" || type == "error" )
				$message.removeClass('success').addClass('error');
			else if ( type == "success" )
				$message.removeClass('error').addClass('success');
			$message.find('p').text(string).fadeIn();
			if ( settings.scrollTo ) $message.scrollTo();
		};
	/**
	 *	message_getInstance
	 *	cria ou recupera instancia de mensagem
	 *
	 *	@return object jQuery
	 */
		function message_getInstance() {
			if ( typeof runtime.message == "undefined" )
				runtime.message = jQuery(settings.validate.messageWrapper).html('<p />').prependTo($form);	
			return runtime.message;
		};
	/**
	 *	observeConfirmationOnSubmit
	 *	verifica confirmação ao enviar formulário
	 *
	 *	@return void
	 */
		function requireConfirmation() {
			$form.find(settings.submit).click(function(e){
				if( confirm(settings.validate.messages.confirm) ) return true; else e.preventDefault();
			});
		};
	/**
	 *	Runtime API
	 *	api para manipulação externa do plugin
	 *
	 *	@return object
	 */
		runtime.api = jQuery.extend({}, runtime.scrollable, {
			goToPage: function(page){
				scrollable_goToPage(page);
			}
		});
	/**
	 *	Plugin Methods Dispatcher
	 *	executa os metodos desejados em "settings"
	 */
		if ( settings.scrollable ) scrollable();
		if ( settings.focus ) observeFocus();
		if ( settings.scrollable ) bindPaginate();
		if ( settings.mask ) maskInput();
		if ( settings.validate ) validate();
		if ( settings.scrollable ) scrollable_preventTab();
		if ( settings.confirm ) requireConfirmation();
	/**
	 *	return
	 *	retorna objeto jQuery do formulário, permite encadeamento jQuery
	 */
		if ( settings.api ) return runtime.api; else return this;
	};
/**
 *	Plugin default parameters
 *	parametros padrões do plugin, permite alteração global:
 *		$.estudo.defaults = {}
 *	@object
 */
	$.fn.estudo.defaults = {
		focus : true,
		api : true,
		scrollTo : true,
		confirm : true,
		paginate : "#paginate",
		wizard : "#wizard",
		submit : "input[type=submit]",
		next : "input[type=button].next",
		prev : "input[type=button].prev",
		loading : "<img src=\"images/ico/ajax-fade.gif\" width=\"16\" height=\"16\" />",
		scrollable : {
			api : true,
			size : 1,
			clickable : false,
			speed : 400
		},
		mask : {
			tel_ddd : "99",
			tel_nro : "9999-9999",
			fax_ddd : "99",
			fax_nro : "9999-9999",
			cel_ddd : "99",
			cel_nro : "9999-9999",
			vmle : "decimal-us",
			valor_frete : "decimal-us",
			valor_seguro : "decimal-us",
			peso : { mask : "9999.999" },
			volume : { mask : "9999.999" }
		},
		validate : {
			messageWrapper : "<div class=\"message\" />",
			rules : {
				empresa : { required : true, maxlength : 50 },
				segmento : { required : false, maxlength : 32 },
				nome : { required : true, maxlength : 32 },
				email : { required : true, mail : true, maxlength : 50 },
				tel_ddd : { required : true, DDD : true },
				tel_nro : { required : true, telefone : true },
				fax_ddd : { emptyDDD : true },
				fax_nro : { emptyTelefone : true },
				cel_ddd : { emptyDDD : true },
				cel_nro : { emptyTelefone : true },
				descncm : { required : true },
				incoterm : { required : true },
				moeda : { required : true },
				vmle : { required : true },
				tipo_frete : { required : true },
				cntr : { required : true },
				embarque : { required : true },
				cot_frete_maritimo : { required : true },
				cot_frete_aereo : { required : true },
				despachante : { required : true },
				entrega_mercadoria : { required : true }
			},
			messages : {
				empresa:{}, 
				segmento:{}, 
				nome:{},
				email:{}, 
				tel_ddd:{}, 
				tel_nro:{}, 
				fax_ddd:{}, 
				fax_nro:{},
				cel_ddd:{}, 
				cel_nro:{}, 
				descncm:{}, 
				incoterm:{}, 
				moeda:{}, 
				vmle:{}, 
				tipo_frete:{}, 
				cntr:{},
				embarque:{}, 
				cot_frete_maritimo:{}, 
				cot_frete_aereo:{}, 
				despachante:{}, 
				entrega_mercadoria:{},
				fail : "",
				err : "",
				confirm : ""
			},
			groups : {
				telefone : "tel_ddd tel_nro",
				fax : "fax_ddd fax_nro",
				celular : "cel_ddd cel_nro"
			},
			errorElement : "p",
			onkeyup : false,
			onfocusout : false
		}
	};
})(jQuery);


	function isEmpty(obj) {
		for(var prop in obj) {
			if(obj.hasOwnProperty(prop))
				return false;
		}
		return true;
	}
