/* written by steffen kuegler */

(function(jQuery) {

jQuery.fn.typeAhead = function(options) 
{            
    jQuery.fn.typeAhead.defaults = 
    {
        debug: false
    };
	
    var opts = jQuery.extend({}, jQuery.fn.typeAhead.defaults, options);
    var args = arguments;
	
	
	function getKeyCode(event) {
	   event = event || window.event;
	   return event.keyCode;
	}
	
	function moveDown( refObj ) {
		// Is there an active elem
		refObj.find('.typeAheadList').show();
		refObj.find('.typeAheadSelecter').addClass('active');
		if(refObj.find('.typeAheadList li.active:visible').length > 0) {			
			next = refObj.find('.typeAheadList li.active:visible').removeClass('active').nextAll(':visible:first');
			if(next.length > 0) {
				next.addClass('active');
			} else {
				refObj.find('.typeAheadList li:visible:first').addClass('active');				
			}
		} else {
			refObj.find('.typeAheadList li:visible:first').addClass('active');
		}		
		value = refObj.find('.typeAheadList li.active:visible').text();
		refObj.find('input.typeAhead').val(value);
	}
	
	function moveUp( refObj ) {
		// Is there an active elem
		refObj.find('.typeAheadList').show();
		refObj.find('.typeAheadSelecter').addClass('active');
		if(refObj.find('.typeAheadList li.active:visible').length > 0) {
					
			prev = refObj.find('.typeAheadList li.active:visible').removeClass('active').prevAll(':visible:first');
			if(prev.length > 0) {
				prev.addClass('active');
			} else {
				refObj.find('.typeAheadList li:visible:last').addClass('active');
				
			}
		} else {
			refObj.find('.typeAheadList li:visible:last').addClass('active');
			
		}	value = refObj.find('.typeAheadList li.active:visible').text();
			refObj.find('input.typeAhead').val(value);	
	}
		
	function takeActive( refObj ) {
		// Is there an active elem
		if(refObj.find('.typeAheadList li.active:visible').length > 0) {			
			value = refObj.find('.typeAheadList li.active:visible').text();		
			rel = refObj.find('.typeAheadList li.active:visible').attr('rel');
			refObj.find('input.typeAhead').val(value);
			refObj.find('input.typeAheadHidden').val(rel);
			if (opts.debug) {
				jQuery('.debug').append(' ---->assign: ' + rel);
			}
			refObj.find('.typeAheadList').fadeOut(100);	
			refObj.find('.typeAheadSelecter').removeClass('active');
			refObj.find('.typeAheadList li').removeClass('match active');
			assignValue ( refObj );
		}
	}
	
	function assignValue ( refObj ) {
		
		hiddenValue = refObj.find('input.typeAheadHidden').val();
		value = refObj.find('input.typeAhead').val();	
		// Is Val Option of SelectField?		
		if(value.toLowerCase() != hiddenValue.toLowerCase() && value.toLowerCase() != hiddenValue.toLowerCase().split(jQuery('#sessionboundary').val())[1]) {
			// No? Then take it
			refObj.find('input.typeAheadHidden').val(value);
			
			if (opts.debug) {
				jQuery('.debug').append(' ----> reassign: ' + value);
			}			
			jQuery('<option />').val(value).text(value).appendTo(refObj.find('select'));			
			refObj.find('select').val(value);
		} else {
			refObj.find('select').val(hiddenValue);
		}				
	}
	
	function initInputField( refObj ) {
		
		refObj.find('.typeAheadSelecter').click(function() {			
			if(jQuery(this).hasClass('active')) {
				refObj.find('.typeAheadList').fadeOut(100);
				refObj.find('.typeAheadSelecter').removeClass('active');
			} else {
				refObj.find('.typeAheadList').show();
				refObj.find('.typeAheadSelecter').addClass('active');
			}		
			refObj.find('input.typeAhead').focus();
		});
		
		refObj.find('.typeAheadList li').hover(function() {			
			jQuery(this).addClass('active');	
		}, function() {			
			jQuery(this).removeClass('active');	
		}).click(function(){
			/*alert("klick");
			takeActive(refObj);*/
		});
		
		refObj.find('input.typeAhead').keyup(function(e) {
			
			// Key DOWN
			if(e.which == "40") {
				moveDown( refObj );
				return;
			}
			
			// Key UP
			if(e.which == "38") {
				moveUp( refObj );
				return;
			}
			
			// Key Enter
			if(e.which == "13") {
				takeActive( refObj );
			}
			
			value = jQuery(this).val();			
			jQuery(this).attr({
				'rel': ''
			});
			
			if(value.length > 0) {
				refObj.find('.typeAheadList li').each(function(i, item) {
					optionVal = jQuery(item).text();
					if(optionVal.toLowerCase().indexOf(value.toLowerCase()) == -1) {
						jQuery(item).removeClass('match active').hide();
					} else {
						jQuery(item).addClass('match').show();					
						start = optionVal.toLowerCase().indexOf(value.toLowerCase())
						length = value.length;					
						text = optionVal.substr(0, start) + '<b><u>' + optionVal.substr(start, length) + '</u></b>' + optionVal.substr(start+length, optionVal.length);					
						jQuery(item).html(text);
					}				
				});
			} else {
				refObj.find('.typeAheadList li').each(function(i, item) {
					optionVal = jQuery(item).removeClass('match').show().text();
					if(e.which != "40" && e.which != "38") {
						jQuery(item).removeClass('active');
					}
					jQuery(item).text(optionVal);
				});
			}
			
			if(refObj.find('.typeAheadList li.match').length > 0 || refObj.find('.typeAheadList li.active').length > 0) {									
				refObj.find('.typeAheadList').show();
				refObj.find('.typeAheadSelecter').addClass('active');
				if(refObj.find('.typeAheadList li.match:visible').length == 1) {
					refObj.find('.typeAheadList li.match:visible').addClass('active');
				}
			} else {
				refObj.find('.typeAheadList').fadeOut(100);	
				refObj.find('.typeAheadSelecter').removeClass('active');			
			}
			
		}).blur(function() {
			takeActive( refObj );
			assignValue( refObj );
			refObj.find('.typeAheadList').fadeOut(100);
			refObj.find('.typeAheadSelecter').removeClass('active');
		}).dblclick(function() {
			refObj.find('.typeAheadSelecter').trigger('click');
		});
	}
	 
    return this.each(function() 
    {
        // Initialisation
        if(typeof jQuery.data(this,"typeAhead") == "undefined")
        {
            var refObj = jQuery(this);
			elemWidth = opts.width ? opts.width : refObj.width();
			refObj.hide();
			
			refObj.wrap(jQuery("<span />").addClass("typeAhead-wrapper"));
			
			jQuery('<input type="text" class="typeAhead" />').css({ 'width' : elemWidth-18 }).insertBefore(refObj);
			
			if(refObj.hasClass('readonly')) { 
				refObj.parent().find('.typeAhead').attr({ readonly: 'readonly'});
			}
			
			jQuery('<input type="hidden" class="typeAheadHidden" />').insertBefore(refObj);
			jQuery('<span class="typeAheadSelecter" />').insertBefore(refObj);
			
			wrapperWidth = opts.width ? opts.width+4 : refObj.parent().width();
			
			listObj = jQuery('<ul class="typeAheadList" />').css({ 'width' : wrapperWidth-2 }).insertBefore(refObj);			
			refObj.find('option').each(function(i, item) {
				if (jQuery(item).text()) {
					jQuery('<li />').attr({ rel : jQuery(item).val()}).text(jQuery(item).text()).appendTo(listObj);
				}								
			});
			initVal = refObj.val();
            refObj.parent().find('.typeAhead').val(refObj.find('option:eq('+refObj.find('option:selected').index()+')').text());
            
            
            
			refObj.parent().find('.typeAheadHidden').val(initVal);
			
			initInputField( refObj.parent() );
			assignValue ( refObj.parent() );
			jQuery.data(this,"typeAhead", true);
        }                    
    });
};
})(jQuery);
