(function($) {
	$.fn.napovez = function(opt) {
		opt = $.extend({}, $.fn.napovez.def, opt);
		
		return this.each(function() {
			var $input = $(this).attr('autocomplete', 'off');
			var $results = $(document.createElement('ul')).addClass(opt.resultsClass).appendTo('body');

			var napTimeout = false;
			var blurTimeout = false;
			var hodnota = '';
			var cache = {};
			
			$input.blur(function() {
				blurTimeout = setTimeout(schovat, 500);
			}).keydown(function(e) {
				switch (e.keyCode) {
					case 9:
						vybrat();
					break;
					case 13:
						vybrat();
						return false;
					break;
					case 27:
						schovat();
						return false;
					break;
	        case 38:
		      	if ($results.is(':visible'))
		      		predchoziRadek();
		      break;
		      case 40:
		      	if ($results.is(':visible'))
		      		dalsiRadek();
					break;
	        default:
						if (hodnota != $input.val()) {
		        	hodnota = $input.val();

		        	smazNapovez();
							napTimeout = setTimeout(napovez, opt.delay);
						}
					break;
				}
				return true;
		  });
		  
			function smazBlur() {
				if (blurTimeout) {
					clearTimeout(blurTimeout);
					blurTimeout = false;
				}
			};
			
			function smazNapovez() {
				if (napTimeout) {
					clearTimeout(napTimeout);
					napTimeout = false;
				}
			};
			
			function resetPosition() {
				offset = $input.offset();
				$results.css({top: (offset.top + $input.outerHeight()) + 'px', left: offset.left + 'px'});
			};
	
			function schovat() {
				smazBlur();
//				tady mozna bude problem, ze se muze napsat dalsi znak
//				smazNapovez();
					
				$results.empty();
				$results.hide();
			};
			
			function napovez() {
				q = $.trim($input.val());

				if (q.length >= opt.minchars) {
					if (opt.cache && (cached = jeCache(q))) {
						schovat();
						zobraz(cached, q);
					} else {
						$.ax(function(jSON) {
							oV = eval('(' + jSON + ')');
							schovat();
							
							if (oV.chyba)
								alert(oV.chyba);
							
							if (oV.vysledek && oV.vysledek.length) {
								zobraz(oV.vysledek, oV.dotaz);
								if (opt.cache)
									pridatDoCache(oV.vysledek, oV.dotaz);
							}
						}, opt.url, opt.param + encodeURIComponent(q), 'get');
					}
				} else
					schovat();
			};
			
			function zobraz(oVys, sDotaz) {
				resetPosition();

				for (var i = 0; i < oVys.length; i++)
					$results.append($('<li' + (oVys[i].zakazany && opt.disabledClass ? ' class="' + opt.disabledClass + '"' : '') + '>' + (opt.matchClass ? oVys[i].zobraz.replace(new RegExp(sDotaz, 'ig'), function(sDotaz) { return '<span class="' + opt.matchClass + '">' + sDotaz + '</span>'; }) : oVys[i].zobraz) + '</li>').data('data', oVys[i]));

				$results.show();

				if (opt.disabledClass) {
					x = $results.children('li').not('.' + opt.disabledClass);
					$results.children('li.' + opt.disabledClass).click(function(e) {
						e.preventDefault();
						e.stopPropagation();
						smazBlur();
						$input.focus();
					});
				} else
					x = $results.children('li');
				
				x.mouseover(function() {
					$results.children('li.' + opt.overClass).removeClass(opt.overClass);
					$(this).addClass(opt.overClass);
				}).mouseout(function() {
					$(this).removeClass(opt.overClass);
				}).click(function(e) {
					e.preventDefault();
					e.stopPropagation();
					
					vybrat();
				});
			};
			
			function vybrat() {
				var oD = false;
				
				if ((oD = $results.children('li.' + opt.overClass).data('data'))) {
					schovat();
					if (opt.dataProcessing)
						opt.dataProcessing($input, oD);
					else
						$input.val(oD.zobraz);
					
					hodnota = oD.zobraz;
				}
			};
			
			function dalsiRadek() {
				var oD = $results.children('li.' + opt.overClass);
				var oT = oD.next('li');
				var iT = $results.children('li').length;

				for (var i = 0; i < iT; i++) {
					if (!oT.length)
						oT = $results.children('li:first-child');

					if (!oT.data('data').zakazany) {
						if (oD.length)
							oD.removeClass(opt.overClass);
						oT.addClass(opt.overClass);
						return;
					}
					
					oT = oT.next('li');
				}
			};
			
			function predchoziRadek() {
				var oD = $results.children('li.' + opt.overClass);
				var oT = oD.prev('li');
				var iT = $results.children('li').length;

				for (var i = 0; i < iT; i++) {
					if (!oT.length)
						oT = $results.children('li:last-child');

					if (!oT.data('data').zakazany) {
						if (oD.length)
							oD.removeClass(opt.overClass);
						oT.addClass(opt.overClass);
						return;
					}
					
					oT = oT.prev('li');
				}
			};
			
			function pridatDoCache(oV, sQ) {
				cache[sQ.toLowerCase()] = oV;
			};
			
			function jeCache(sQ) {
				sQ = sQ.toLowerCase();
				return cache[sQ] ? cache[sQ] : null; 
			};
			
		});
	};
	
	$.fn.napovez.def = {
		url: 'rpc.php',
		param: '', 
		cache: true, 
		delay: 350, 
		resultsClass: 'nas_vysl', 
		matchClass: 'nas_vyb', 
		overClass: 'nas_over', 
		disabledClass: 'nas_zak',
		minchars: 3, 
		dataProcessing: false
	};
})(jQuery);
