/*
 * This autocompleter should be constructed with a given populator function.
 * The populator function should call the setChoices(choices) method on this autocompleter
 * where 'choices' is the array of choices to be displayed in the autocomplete div.
 */

Autocompleter.DWR = Class.create();
Autocompleter.DWR.prototype = Object.extend(new Autocompleter.Base(), {
   initialize: function(element, update, populator, options) {
     this.baseInitialize(element, update, options);
     this.options.array = new Array(0);
     this.options.sortedArray = new Array(0);
     this.populator = populator;
     this.options.template = new Template('<li><span class="item-label">#{label}</span><span class="item_info">#{info}</span></li>');
     if (this.options.afterUpdateElement ) {
         this.afterUpdateCallback = this.options.afterUpdateElement;
         this.options.afterUpdateElement = this.afterUpdateElement.bind(this);
     }
   },

   // called by the autocompleter on an event.
   getUpdatedChoices: function() {
     this.populator(this, this.getToken()); // this is the populator specified in the constructor.
   },

    afterUpdateElement: function(element,selectedElement) {
         this.afterUpdateCallback(element, selectedElement, this.options.sortedArray[this.index]);
     },

   // should be called by the populator (specified in the constructor)
   setChoices: function(array) {
     this.options.array = array;
     this.updateChoices(this.options.selector(this));
   },

   setOptions: function(options) {
     this.options = Object.extend({
       choices: 15,
       partialSearch: true,
       partialChars: 2,
       ignoreCase: true,
       fullSearch: true,
       selector: function(instance) {
         var entry     = instance.getToken();
		 var valueSelector = instance.options.valueSelector;		 
		 var tokenRegExp = new RegExp(entry, 'i');
		 
		 var html = '<ul>';
		 for (var i = 0; i < instance.options.array.length; i++) {
			 var elem = valueSelector(instance.options.array[i]);
	         var s = elem.split('|', 2);
			 html += instance.options.template.evaluate({
				 label: s[0].sub(tokenRegExp, function(match) {
					 return '<strong>' + match + '</strong>';
				 }),
				 info: s[1]
			 });
		 }
		 html += '</ul>';

		 instance.options.sortedArray = instance.options.array;

		 return html;
       },
       valueSelector: function(object){ return object; }
     }, options || {});
   },
   
	markPrevious: function() {
		this.index = (this.index > 0) ? this.index - 1 : this.entryCount-1;
		/* this way makes the window scrolling brutally in addition of the list scrolling
		this.getEntry(this.index).scrollIntoView(true); */
		var entry = this.getEntry(this.index);
		var layer = entry.up(1); // "update" element (suggestions list)
		var position = entry.positionedOffset();
		var overlap = {
			top: layer.scrollTop - position[1],
			bottom: (position[1] + entry.getHeight()) - (layer.getHeight() + layer.scrollTop)
		}
		var threshold = (0.1 * entry.getHeight());
		if(overlap.top > threshold) {
			layer.scrollTop = position[1];
		}
		else if(overlap.bottom > threshold) {
			layer.scrollTop += overlap.bottom;
		}
	 
	},
  
	markNext: function() {
		this.index = (this.index < this.entryCount - 1) ? this.index + 1 : 0;
		/* this way makes the window scrolling brutally in addition of the list scrolling
		this.getEntry(this.index).scrollIntoView(false); */
		var entry = this.getEntry(this.index);
		var layer = entry.down(1); // "update" element (suggestions list)
		var position = entry.positionedOffset();
		var overlap = {
			top: layer.scrollTop - position[1],
			bottom: (position[1] + entry.getHeight()) - (layer.getHeight() + layer.scrollTop)
		};
		var threshold = (0.1 * entry.getHeight());
		if(overlap.top > threshold) {
			layer.scrollTop = position[1];
		}
		else if(overlap.bottom > threshold) {
			layer.scrollTop += overlap.bottom;
		}
	 
	}
});

