/*
 * jQuery search suggester, db lookup and google geoloc suggestions
 * @author Daniel Honzik
 * @version 1.0
 * @site restaurace.cz  
 */
 
(function($) {  

  var locationCache = [];

  // jquery fn
  $.fn.suggest = function(map) {    
    var $that = this;
    var $viewer = createViewer(this);
    var timer = {};
 
    this.bind('keyup', function(k){
      if ($.inArray(k.keyCode, [13, 16, 17, 18, 20, 27, 33, 34, 35, 37, 38, 39, 40, 144]) == -1 && $that.val() != '') {
        clearTimeout(timer);
        timer = setTimeout((map ? searchMap : searchWeb), 200, [$that, $viewer, map]);
      } else if (k.keyCode == 40) {
        iterate(1, $that, $viewer, map);
      } else if (k.keyCode == 38) {
        iterate(-1, $that, $viewer, map);
      } else if (k.keyCode == 27 || k.keyCode == 13) {
        $viewer.fadeOut();
      }      
    }).bind('focus', function(){
      $.data($that, { active: true });
    }).bind('blur', function(){
      $.data($that, { active: false });
      $viewer.fadeOut();      
    });       
  };
  
  // remove all html and its content
  function cleaner(html) {
    return html.replace(/(<[^>]+>(.*)<[^>]+>)/, '');
  }
  
  // set single value or assign geolocation data for the map
  function setValue(e, v, i, map) {
    if (locationCache.length > 0 && map) {
      e.val(v);
      $.data(e, { latitude: locationCache[i].geometry.location.b,
                  longitude: locationCache[i].geometry.location.c }); 
    } else {
      e.val(v);
    }
  }
  
  // key navigation and value assignment
  function iterate(direction, e, viewer, map) {
    var items = viewer.find('li');
    var selectedValue = '';
    var selectedIndex = -1;
    
    if (viewer.css('display') == 'none' || items.length  === 0) {
      return;
    }
    
    items.each(function(i){
      var $this = $(this);
      if ($this.hasClass('selected')) {
        $this.removeClass('selected');
        selectedIndex = i;
      }
    });
    
    if ((selectedIndex == -1 || selectedIndex == items.length-1) && direction == 1) {
      selectedValue = viewer.find('li:eq(0)').addClass('selected').html();
      selectedIndex = 0;
    } else if (selectedIndex === 0 && direction == -1) {
      selectedValue = viewer.find('li:eq('+(items.length-1)+')').addClass('selected').html();
      selectedIndex = items.length - 1;
    } else {
      selectedValue = viewer.find('li:eq('+(selectedIndex + direction)+')').addClass('selected').html();
      selectedIndex = selectedIndex + direction;
    }
    setValue(e,cleaner(selectedValue),selectedIndex, map);
  }
  
  // ajax simple search for website queries
  function searchWeb(args) {
    var e = args[0], v = args[1], content = '';
    
    $.post('/ajax.php', { 'action': 'search-web', 'q': e.val() }, function(j){
      if (j.wordCount > 0) {
        for(var i = 0; i < j.words.length; i++) {
          content += '<li>' + j.words[i].word + '<span>' + j.words[i].count + '&times;</span></li>';
        }
        showViewer(e, v, content);
      } else {
        hideViewer(v);
      }      
    }, 'json');
  }
  
  // ajax geoloc search for assigned google map
  function searchMap(args) {
    var e = args[0], v = args[1], map = args[2], content = '';
    
    map.geoSearch(e.val(), function(results) {
      locationCache = [];
      $.removeData(e, 'latitude');
      $.removeData(e, 'longitude');
      
      if (results.length > 0) {
      
        for(var key in results) {
          content += '<li>' + results[key].formatted_address + '</li>';
          locationCache.push(results[key]);
        }
        showViewer(e, v, content, true);
      } else {
        hideViewer(v);
      }
    });
  }
  
  // quick viewer hide
  function hideViewer(viewer) {
    viewer.css('display', 'none');
  }
  
  // show includes reposition, rebind its items and show in the end
  function showViewer(e, viewer, content, map) {
    if ($.data(e, 'active') === false) {
      return;
    }
    
    viewer.find('li').unbind('mouseover mouseout click');
    viewer.html(content);
    viewer.find('li').each(function(index){
      var $this = $(this);
      $this.bind('mouseover mouseout click', function(item){
        if (item.type == 'mouseover') {
          $this.addClass('hover');
        } else if (item.type == 'mouseout') {
          $this.removeClass('hover');
        } else {
          setValue(e,cleaner($this.html()),index,map);
        } 
      });
    });
    
    viewer.css('left', e.position().left + parseInt(e.css('margin-left'), 10))
      .css('top', e.position().top + e.height() + parseInt(e.css('margin-top'), 10) + parseInt(e.css('margin-bottom'), 10) + 4)
      .css('width', e.width() + parseInt(e.css('padding-left'), 10) + parseInt(e.css('padding-right'), 10))
      .css('display', 'block');
  }
  
  // simple viewer creation to keep element pointer
  function createViewer() {
    var viewer = document.createElement('ul');
    $(viewer).addClass('suggest');
    $('body').append(viewer);
    return $(viewer); 
  }

})(jQuery);
