//TODO: insert loadinggif after the inout element
jQuery.fn.autoComplete = function(GEToptions) {
   // if there are no elements selected return
   // See guide to write jQuery plugins!! You should use
   // this.foreach(function(){...}); to iterate over input elements.
   // for now this should be enough
   if (!this.length)
      return this;

   jQuery(this).parents().filter('form').attr('autocomplete', 'off');
   var usedInputBox = this;
   var focused = false;
   var lastValue = jQuery(this).val();
   var clone = jQuery(usedInputBox).clone(true);
   jQuery(clone).removeAttr('id').removeAttr('class');

   // setup blur functions if there are any
   var blur = {};
   var events = jQuery.data(jQuery(clone)[0],'events')
   if (typeof(events) != 'undefined' && typeof(events.blur) != 'undefined')
      jQuery.extend(blur, events['blur'])

   var oldBlurFunction = function() {
      for (guid in blur) {
         if (guid != 'undefined')
            blur[guid].apply(usedInputBox);
      }
   };
   jQuery(this).unbind('blur');
   jQuery(this).focus(function(){
      focused = true;
      if (options['validatedClass'] != "")
         jQuery(this).removeClass(options['validatedClass']);
      lastValue = jQuery(this).val();
   });
   var defaultOptions = {
      'header' : '<div class="AC_header_arrow"></div><div class="AC_header_left"><div class="AC_header_right"><div class="AC_header"></div></div></div>',
      'footer' : '<div class="AC_footer_left"><div class="AC_footer_right"><div class="AC_footer"></div></div></div>', 
      'body'   : '<div class="AC_body_left"><div class="AC_close"></div><div class="AC_body"></div></div>', 
      'requestParam'    : 'actualInput', 
      'fadeIn'          : '1000', 
      'fadeOut'         : '1000', 
      'keyTime'         : '300', 
      'autocompletebox' : '<div class="AC_positioner"></div>',
      'returnData'      : '<div class="AC_data"></div>',
      'loadingGifPath'  : 'http://dev1.heimat.de/module/jscript/lib/jquery_plugins/autocomplete/',
      'onSelectFuntion' : 'AC_onSelectFunction(selectedElement)',
      'appendBlur'      : '',
      'validatedClass'  : ''
   };
   jQuery.extend(defaultOptions, GEToptions);
   var options = defaultOptions;
   if (typeof(loadingGifPath) != "undefined")
      options['loadingGifPath'] = loadingGifPath;
   var callback = function(JSONdata) {
      // data is available
      jQuery('.AC_loading').remove();
      if (focused) {
         var returnData  = jQuery(options['returnData']);
         jQuery(returnData).append('<div class="AC_root">'+jQuery(usedInputBox).attr('id')+'</div>');
         if (JSONdata['results'] != undefined) {
            for ( keyVar in JSONdata['results'] ) {
               if (JSONdata['results'][keyVar]['info'] != undefined) {
                  jQuery(returnData).append('<div class="AC_entry">'
                     +'<div class="AC_input_data">'
                     +JSONdata['results'][keyVar]['value']
                     +'</div>'
                     +'<div class="AC_show_data">'
                     +JSONdata['results'][keyVar]['info']
                     +'</div>'
                     +'<input type="hidden" class="AC_data_id" value="'
                     +JSONdata['results'][keyVar]['id'] // store entry id
                     +'" />'
                  +'</div>');
               }
            }
            jQuery(returnData).children('.AC_entry').click(function() {
               lastValue = jQuery(this).children('.AC_input_data').html();
               jQuery('#'+jQuery(this).parent().children('.AC_root').html()).val(jQuery(this).children('.AC_input_data').html());
               var selectedElement = this;
               var itemId = jQuery(this).children('.AC_data_id').val();
               jQuery("#" + usedInputBox[0].id + "Id").val(itemId); // set hidden value for the id
               eval(options['onSelectFuntion']);
               if (options['validatedClass'] != "")
                  jQuery(usedInputBox).addClass(options['validatedClass']);
               jQuery('.AC_positioner').fadeOut(options['fadeOut'],function() {
                  jQuery('.AC_positioner').remove();
               });
               oldBlurFunction();
               return false;
            });
         } else if (JSONdata['error']) {
            jQuery(returnData).append('<div class="AC_entry">'
               + JSONdata['error']
               +'</div>'
            +'</div>');
            jQuery(returnData).children('.AC_entry').click(function() {
               jQuery('.AC_positioner').fadeOut(options['fadeOut'], function() {
                  jQuery('.AC_positioner').remove();
               });
               jQuery(usedInputBox).val('');
               oldBlurFunction();
               return false;
            });
         } else {
            jQuery(returnData).append('<div class="AC_entry">'
               +'<div class="AC_input_data"></div>'
               +'<div class="AC_show_data">'
                  +JSONdata['error']
               +'</div>'
            +'</div>');
            jQuery(returnData).children('.AC_entry').click(function() {
               jQuery('.AC_positioner').fadeOut(options['fadeOut'], function() {
                  jQuery('.AC_positioner').remove();
               });
               jQuery(usedInputBox).val('');
               oldBlurFunction();
               return false;
            });
         }
         var AutoCompleteBox = jQuery(options['autocompletebox']);
         jQuery(AutoCompleteBox)
            .css('top',jQuery(usedInputBox).offset().top+jQuery(usedInputBox).outerHeight()+'px')
            .css('left',jQuery(usedInputBox).offset().left+'px')
            .css('width',jQuery(usedInputBox).outerWidth()+'px');
         if (typeof(options['width']) != 'undefined')
            jQuery(AutoCompleteBox).css('width',options['width']+'px');
         jQuery(AutoCompleteBox)
            .append(options['header'])
            .append(options['body'])
            .append(options['footer'])
            .hide();
         jQuery('body').append(AutoCompleteBox);
         jQuery('.AC_body').append(returnData);
         jQuery('.AC_entry').hover(function() {
            jQuery(this).addClass('AC_hoveredItem');
         }, function() {
            jQuery(this).removeClass('AC_hoveredItem');
         });
         jQuery('.AC_close').click(function() {
            jQuery('.AC_positioner').fadeOut(options['fadeOut'], function() {
               jQuery('.AC_positioner').remove();
            });
            jQuery(usedInputBox).val('');
            oldBlurFunction();
            return false;
         });
         jQuery('.AC_positioner').fadeIn(options['fadeIn']);
      }
   }
   timeout = null;
   jQuery(this).blur(function() {
      focused = false;
      if (jQuery(this).val() != lastValue) {
         jQuery(usedInputBox).val('');
         jQuery('.AC_positioner').fadeOut(options['fadeOut'],function() {
            jQuery('.AC_positioner').remove();
         });
      } else if (options['validatedClass'] != "") {
         jQuery(this).addClass(options['validatedClass']);
      }
      oldBlurFunction();
      if (options['appendBlur'] != "")
         options['appendBlur']();
   });
   jQuery(this).keydown(function(keyCapture) {
      if (keyCapture.which == '38' && jQuery('.AC_positioner').html() != "") {
         // up arrow pressed
         if (jQuery('.AC_data > .AC_hoveredItem').length == 0) {
            jQuery('.AC_data > .AC_entry:last').addClass('AC_hoveredItem');
            jQuery('.AC_data').parent()[0].scrollTop = jQuery('.AC_data').parent()[0].scrollHeight;
         } else {
            var activeElement = jQuery('.AC_data > .AC_hoveredItem');
            jQuery(activeElement).removeClass('AC_hoveredItem');
            activeElement = jQuery(activeElement).prev();
            if (jQuery(activeElement).hasClass('AC_root')) {
               activeElement = jQuery('.AC_data > .AC_entry:last');
               jQuery('.AC_data').parent()[0].scrollTop = jQuery('.AC_data').parent()[0].scrollHeight;
            }
            jQuery(activeElement).addClass('AC_hoveredItem');
         }
         var offsetElement = jQuery('.AC_data .AC_hoveredItem')[0].offsetTop;
         offsetElement -= jQuery('.AC_data').parent()[0].offsetTop;
         var scrollTop = jQuery('.AC_data').parent()[0].scrollTop;
         if (offsetElement < scrollTop)
            jQuery('.AC_data').parent()[0].scrollTop = jQuery('.AC_data .AC_hoveredItem')[0].offsetTop-28;
      } else if (keyCapture.which == '40' && jQuery('.AC_positioner').html() != "") {
         // down arrow pressed
         if (jQuery('.AC_data > .AC_hoveredItem').length == 0) {
            jQuery('.AC_data > .AC_entry:first').addClass('AC_hoveredItem');
            jQuery('.AC_data').parent()[0].scrollTop = 0;
         } else {
            var activeElement = jQuery('.AC_data > .AC_hoveredItem');
            jQuery(activeElement).removeClass('AC_hoveredItem');
            activeElement = jQuery(activeElement).next();
            if (activeElement.length == 0) {
               activeElement = jQuery('.AC_data > .AC_entry:first');
               jQuery('.AC_data').parent()[0].scrollTop = 0;
            }
            jQuery(activeElement).addClass('AC_hoveredItem');
         }
         var offsetElement = jQuery('.AC_data .AC_hoveredItem')[0].offsetTop;
         offsetElement -= jQuery('.AC_data').parent()[0].offsetTop;
         offsetElement += jQuery('.AC_data .AC_hoveredItem')[0].clientHeight;
         var scrollTop = jQuery('.AC_data').parent()[0].scrollTop;
         scrollTop += jQuery('.AC_data').parent()[0].clientHeight;
         if (offsetElement > scrollTop)
            jQuery('.AC_data').parent()[0].scrollTop = jQuery('.AC_data .AC_hoveredItem')[0].offsetTop-210;
      } else if (keyCapture.which == '13' && jQuery('.AC_data > .AC_hoveredItem').length > 0) {
         // enter pressed. user selected something. hide autocompletion box.
         lastValue = jQuery(this).children('.AC_input_data').html();
         jQuery(usedInputBox).blur();
         var selectedElement = jQuery('.AC_data > .AC_hoveredItem');
         jQuery('#'+jQuery(selectedElement).parent().children('.AC_root').html()).val(jQuery(selectedElement).children('.AC_input_data').html()); // enter the selected entry to the input box
         var itemId = jQuery(selectedElement).children('.AC_data_id').val();
         jQuery("#" + usedInputBox[0].id + "Id").val(itemId); // set hidden value for the id
         eval(options['onSelectFuntion']);
         if (options['validatedClass'] != "")
            jQuery(this).addClass(options['validatedClass']);
         jQuery('.AC_positioner').fadeOut(options['fadeOut'], function() {
            jQuery('.AC_positioner').remove();
         });
         oldBlurFunction();
         return false;
      } else if(keyCapture.which == '13' || jQuery(usedInputBox).val() != lastValue) {
         // starting the search after pressing enter or waiting too long after last keyup
         if (typeof(autoCompleteAjaxRequest) != "undefined")
            autoCompleteAjaxRequest.abort();
         jQuery('.AC_loading').remove();
         if (jQuery('#'+jQuery('.AC_root').html()).attr('id') != jQuery(usedInputBox).attr('id'))
            jQuery('#'+jQuery('.AC_root').html()).val('');
         jQuery('.AC_positioner').remove();
         if (timeout)
            clearTimeout(timeout);
         timeout = setTimeout(function() {
            if (typeof(jQuery(usedInputBox).val()) != 'undefined' && jQuery(usedInputBox).val() != "" && jQuery(usedInputBox).val().length > 1) {
               var loadingGif = jQuery('<img src="'+options['loadingGifPath']+'loading.gif" class="AC_loading" alt=""/>');
               jQuery(loadingGif)
                  .css('position','absolute')
                  .css('left', jQuery(usedInputBox).offset().left+jQuery(usedInputBox).outerWidth()-20+'px')
                  .css('top',jQuery(usedInputBox).offset().top+(jQuery(usedInputBox).outerHeight()/2)-(jQuery(usedInputBox).innerHeight()/2)+'px')
                  .css('height',jQuery(usedInputBox).height()+'px');
               jQuery('body').append(jQuery(loadingGif));
               autoCompleteAjaxRequest = jQuery.get(
                  options['requestUrl'],
                  options['requestParam']+'='+jQuery(usedInputBox).val(),
                  callback, 'json'
               );
            }
         },options['keyTime']);
      }
   });
   
   function AC_onSelectFunction(clicked)
   {
      jQuery(usedInputBox).css('vertical-align','top')
      jQuery(usedInputBox).click(function() {
         if (jQuery(this).hasClass('AC_hoveredItem')) {
            jQuery(this).removeClass('AC_hoveredItem');
            if (jQuery('#'+jQuery('.AC_root').html()).attr('id') != jQuery(usedInputBox).attr('id')) {
               jQuery('#'+jQuery('.AC_root').html()).val('');
            }
            jQuery('.AC_positioner').remove();
            autoCompleteAjaxRequest = jQuery.get(
               options['requestUrl'],
               options['requestParam']+'='+jQuery(usedInputBox).val(),
               callback, 'json'
            );
         }
      });
   }

   return this;
};
