

var AUCM = {

  data: [],
  inRef: null,
  resultsRef: null,
  coverRef: null,
  minChrs: 2,
  maxLines: 10,
  results: [],
  typedText: '',
	selectedIndex: -1,
	noResultsText: 'No matching locations found',
	
  init: function(inID, data)
  {
    AUCM.data = data;
    AUCM.inRef = $('#' + inID).bind('keyup', AUCM.handleInput).bind('keypress', AUCM.handleInput).bind('blur', function() { setTimeout(AUCM.clear, 200); })[0];
    AUCM.resultsRef = $('<div class="auto-compl"></div>').hide().appendTo(document.body)[0];
    AUCM.coverRef = $('<iframe src="cover.html" class="autocompl" frameborder="0" scrolling="no"></iframe>').hide().appendTo(document.body)[0];
    try 
    { 
			AUCM.inRef.focus(); 
		}
    catch(e) {}
  },

	handleInput: function(ev)
	{
		if(ev.which == 13)
		{	// enter
			if(ev.type == 'keyup') return;
			
			//ev.stopPropagation();
			//ev.preventDefault();
			
			if($.trim(AUCM.inRef.value).length > 0 &&AUCM.selectedIndex == -1 && AUCM.results.length > 0)
			{
				AUCM.inRef.value = AUCM.results[0].text;
			}
			
			AUCM.results = [];
			AUCM.selectedIndex = -1;
			AUCM.typedText = '';
			
			AUCM.clear();
			return;
		}
		
		if(ev.type == 'keypress') return;
		
		if(ev.which == 40)
		{	// down
			AUCM.goToNextResult();
			return;
		}
		else if(ev.which == 38)
		{	// up
			AUCM.goToPrevResult();
			return;
		}
		else if(ev.which == 27)
		{	// esc
			AUCM.inRef.value = AUCM.typedText;
			AUCM.results = [];
			AUCM.selectedIndex = -1;
			AUCM.typedText = '';
			AUCM.clear();
			return;
		}
		
		if(AUCM.typedText != AUCM.inRef.value /* && AUCM.selectedIndex == -1 */)
		{
			if(AUCM.inRef.value.length >= AUCM.minChrs)
				AUCM.updateResult();
			else AUCM.clear();
		}
		
    if(AUCM.results.length == 0 && AUCM.selectedIndex == -1 && AUCM.inRef.value.length >= AUCM.minChrs)
			AUCM.showNoResults();
	},
	
	updateResult: function()
	{
		AUCM.typedText = AUCM.inRef.value;
		AUCM.results = [];
		AUCM.selectedIndex = -1;
		
    var expr = new RegExp("^" + AUCM.typedText, 'i');
    $(AUCM.data).filter( function(){ return !!this.match(expr); }).each(function(n)
    {
      AUCM.results[AUCM.results.length] = {text:this, pos: n};
    });
		
		AUCM.redrawResult();
	},
	
	redrawResult: function()
	{
		AUCM.clear();
		if(AUCM.results.length == 0) return;
		
		$(AUCM.results).each(function(){
			$('<div>' + this.text + '</div>').attr('pos', this.pos).hover(AUCM.resultOver, AUCM.resultOut).appendTo(AUCM.resultsRef);
		});
		$('div', AUCM.resultsRef).bind('click', AUCM.selectResult);
		AUCM.show();
	},

  selectResult: function(ev)
  {
    AUCM.inRef.value = $(this).text();
    AUCM.inRef.focus();
    AUCM.clear();
  },

  resultOver: function(ev)
  {
    $(this).addClass('selected');
  },

  resultOut: function(ev)
  {
    $('div', AUCM.resultsRef).removeClass('selected');
  },

  show: function()
  {
    var pos = $(AUCM.inRef).position();
    pos.top += $(AUCM.inRef).height() + 4;
    
    $(AUCM.coverRef).width($(AUCM.inRef).width() + 5).height($(AUCM.resultsRef).height());
    $(AUCM.coverRef).css({ top: pos.top, left: pos.left }).show();
    
    $(AUCM.resultsRef).width($(AUCM.inRef).width() + 5);
    $(AUCM.resultsRef).css({ top: pos.top, left: pos.left }).show();
  },

  clear: function()
  {
		$('div', AUCM.resultsRef).unbind('click');
    $(AUCM.resultsRef).hide();
    $(AUCM.coverRef).hide();
    $(AUCM.resultsRef).html("");
  },
  
  goToNextResult: function()
  {
		if(AUCM.results.length == 0) return;
		if(AUCM.results.length > AUCM.selectedIndex + 1) AUCM.selectedIndex ++;
		AUCM.refreshResult();
  },
  
  goToPrevResult: function()
  {
		if(AUCM.results.length == 0) return;
		if(AUCM.selectedIndex > -1) AUCM.selectedIndex --;
		if(AUCM.selectedIndex == -1) AUCM.inRef.value = AUCM.typedText;
		AUCM.refreshResult();
  },
  
  refreshResult: function()
  {	// update Up/Down keystroke
		$('div', AUCM.resultsRef).removeClass('selected');
		$('div[pos=' + AUCM.selectedIndex + ']', AUCM.resultsRef).addClass('selected');
		AUCM.inRef.value = AUCM.results[AUCM.selectedIndex].text;
  },
  
  isValid: function()
  {
    var expr = new RegExp("^" + $.trim(AUCM.inRef.value) + "$", 'i');
    return ($(AUCM.data).filter(function() { return !!this.match(expr); }).size() > 0);
  },
  
  showNoResults: function()
  {
    $(AUCM.resultsRef).html("");
		$('<div style="color:#ff0000; font-weight:bold;"></div>').text(AUCM.noResultsText).appendTo(AUCM.resultsRef);
		AUCM.show();
  }

}
