/**
 * Vytvoří instanci našeptávače.
 *
 * @param String paramInputId id textového pole
 * @param String paramUrl url pro získávání dat
 */
function Suggest(paramInputId, paramUrl)
{

	var inputEl = document.getElementById(paramInputId);
	var suggestEl = document.getElementById(paramInputId + '-suggest');
	var url = paramUrl;

	var dataTimeoutId = null;
	var hideTimeoutId = null;
	var request = null;

	var data = [];
	var selectedItem = null;

	var maxCount = 10;
	
	// initializace
	init();

	/**
	 * Nastaví našeptávač.
	 *
	 * @access private
	 */
	function init()
	{
		// initializace textového pole
	    inputEl.onkeyup = inputKeyUp;
	    if (document.all) {
	        inputEl.onkeydown = inputKeyDown;
	    } else {
	        inputEl.onkeypress = inputKeyDown;
	    }
	    inputEl.onclick = unselectItem;
	    inputEl.onblur = function() {hideTimeoutId = window.setTimeout(hide, 500);}

		// initializace našeptávače
		var list = document.createElement('ul');
		for (var i = 0; i < maxCount; i++) {
			var item = document.createElement('li');
		    item.onclick = suggestItemClick;
			item.onmouseover = suggestItemOver;
			item.onmouseout = suggestItemOut;
			list.appendChild(item);
		}
		suggestEl.innerHTML = '';
		suggestEl.appendChild(list);
		
	};

	/**
	 * Ochytává puštění klávesy v textovém poli.
	 *
	 * @access private
	 * @param Event event
	 */
	function inputKeyUp(event)
	{
	    event = event || window.event;  // IE
		switch (event.keyCode) {
		case 13:    // enter
		case 17:    // ctrl
		case 18:    // alt
		case 27:    // escape
		case 44:    // print screen
		case 45:    // insert
		    break;
		case 8:    // backspace
		case 46:    // delete
            window.clearTimeout(dataTimeoutId);
            unselectItem();
            dataTimeoutId = window.setTimeout(getData, 100);
            break;
		default:
		    if (event.keyCode > 40) {
	            window.clearTimeout(dataTimeoutId);
	            dataTimeoutId = window.setTimeout(getData, 250);
			}
		}
	};
	
	/**
	 * Ochytává stisk klávesy v textovém poli.
	 *
	 * @access private
	 * @param Event event
	 */
	function inputKeyDown(event)
	{
	    event = event || window.event;  // IE
		switch (event.keyCode) {
		case 13:    // enter
		case 39:    // doprava
	        if (selectedItem) {
	            inputEl.value = selectedItem.firstChild.nodeValue;
	            if (event.keyCode != 13) {    // enter spustí vyhledávání, není potřeba našeptávač
					getData();
				}
	        }
		    return true;
		case 38:    // nahoru
		case 40:    // dolů
		    selectItem(event.keyCode);
		    return false;
		case 27:    // escape
		    hide();
		    return true;
		default:
		    return true;
		}
	};
	
	/**
	 * Načte data ze serveru.
	 *
	 * @access private
	 */
	function getData()
	{
		// zrušení předchozího požadavku
		if (request) {
			request.abort();
			request = null;
		}

        if (inputEl.value) {
			try {
				
				request = getRequest();
				request.open('GET', url + '?&out=json&q=' + inputEl.value, true);
				//request.open('GET', 'http://vip07.imagic.cz/!suggest/ajax.php?out=json&q=auto', true);
				request.onreadystatechange = function() {
					if (request.readyState == 4) {
						try {
							if (request.status == 200) {
							    try {
							        eval('data = (' + request.responseText + ');');
									show();
								} catch (e) {
								    // chybná data od serveru
								}
							}
						} catch (e) {
						    // výjimka vyhozená po abort
						}
					}
				};
				request.send(null);
			} catch (e) {
				// nepodařilo se vytvořit XMLHttpRequest
				alert('nepodařilo se vytvořit XMLHttpRequest');
			}
        } else {
            hide();
		}
	};

	/**
	 * Zobrazí našeptávač.
	 *
	 * @access private
	 */
	function show()
	{
        window.clearTimeout(hideTimeoutId);
        
        var show = false;
        for (var i = 0; i < maxCount; i++) {
            var item = suggestEl.firstChild.childNodes[i];
            if (data[i]) {
				item.innerHTML = data[i][0] + '<span>' + data[i][1] + 'x</span>';
                item.style.display = 'block';
                show = true;
            } else {
                item.innerHTML = '';
                item.style.display = 'none';
            }
        }
        if (show) {
			suggestEl.style.display = 'block';
		} else {
	        unselectItem();
			suggestEl.style.display = 'none';
		}
	};

	/**
	 * Vybere položku našeptávače.
	 *
	 * @access private
	 * @param integer keyCode kód klávesy
	 */
	function selectItem(keyCode)
	{
        if (data.length > 0) {
            if (selectedItem) {
                selectedItem.className = '';
                if (keyCode == 40) {	// dolů
                    selectedItem = (selectedItem == suggestEl.firstChild.childNodes[data.length - 1])
						? suggestEl.firstChild.childNodes[0]
						: selectedItem.nextSibling;
                } else {    // nahoru
                    selectedItem = (selectedItem == suggestEl.firstChild.childNodes[0])
						? suggestEl.firstChild.childNodes[data.length - 1]
						: selectedItem.previousSibling;
                }
            } else {
                var selectedIndex = (keyCode == 40) ? 0 : data.length - 1;
                selectedItem = suggestEl.firstChild.childNodes[selectedIndex];
            }

            selectedItem.className = 'active';
        }
	};

	/**
	 * Zruší výběr položky našeptávače.
	 *
	 * @access private
	 */
	function unselectItem()
	{
        if (selectedItem) {
            selectedItem.className = '';
            selectedItem = null;
        }
	};
	
	/**
	 * Skryje našeptávač.
	 *
	 * @access private
	 */
	function hide()
	{
		// je zde kvůli rychlosti, ačkoliv totéž udělá nasledně volaná funkce show()
        unselectItem();
		suggestEl.style.display = 'none';

		data = [];
		show(); // protože jsou data prázdná, tak našeptávač promaže a skryje
	};

	/**
	 * Kliknutí na položku našeptávače.
	 *
	 * @access private
	 * @param Event event
	 */
	function suggestItemClick(event)
	{
		inputEl.value = this.firstChild.nodeValue;
		//inputEl.form.submit();
		return false;
	};

	/**
	 * Najetí na položku našeptáváče.
	 *
	 * @access private
	 * @param Event event
	 */
    function suggestItemOver(event)
    {
        if (selectedItem) {
            selectedItem.className = '';
        }
        selectedItem = this;
        selectedItem.className = 'active';
    };

	/**
	 * Opuštění položky našeptávače.
	 *
	 * @access private
	 * @param Event event
	 */
    function suggestItemOut(event)
    {
		unselectItem();
	};

	/**
	 * Vrátí instanci XMLHttpRequestu.
	 *
	 * @access private
	 * @return XMLHttpRequest
	 * @throws Error když se nepodaří vytvořit instanci
	 */
	function getRequest()
	{
		
		if (typeof XMLHttpRequest != 'undefined') {
			return new XMLHttpRequest();
		} else {
			
			try {
				return new ActiveXObject('Msxml2.XMLHTTP');
			} catch (e) {
				try {
					return new ActiveXObject('Microsoft.XMLHTTP');
				} catch (E) {
					throw new Error('XMLHttpRequest není dostupný.');
				}
			}
		}
	};
};

