var autocompletionList = null;

var httpRequest = null;
var ConnectionTypes = [
  function() { return new XMLHttpRequest() },
  function() { return new ActiveXObject('Microsoft.XMLHTTP') },
  function() { return new ActiveXObject('Msxml2.XMLHTTP') }
];
for ( i = 0 ; i < ConnectionTypes.length ; ++i ) {
  try {
    httpRequest = ConnectionTypes[ i ]();
    break;
  } catch ( e ) {}
}

function AutocompletionList( textfield_id, list_id, processingPage ) {

  this.textfield = document.getElementById( textfield_id );
  this.textfield.autocompletionList = this;
  this.textfield.onkeyup = this.onKeyUp;
  this.textfield.onkeydown = this.onKeyDown;
  this.textfield.onblur = function() { this.autocompletionList.hide(); };

  this.element = document.getElementById( list_id );

  this.processingPage = processingPage;

  this.data = [];

  this.listItems = [];

  this.selectedIndex = -1;
}

AutocompletionList.prototype = {

  onKeyUp : function( e ) {

    if ( ! e ) {
      e = window.event;
    }

    switch( e.keyCode ) {
      case 37: // left key
      case 39: // right key
        return;

      case 27: // esc key
        this.autocompletionList.hide();

      case 38: // up key
        this.autocompletionList.selectPrevious();
        break;

      case 40: // down key
        this.autocompletionList.selectNext();
        break;

      case 9: // tab key
      case 13: // return key
        break;

      default: // any other key
        var words = this.value.split( ', ' );
        var lastWord = words[ words.length-1 ];
        if ( lastWord.indexOf( ',' ) < 0 && lastWord.length > 0 ) {
          this.autocompletionList.sendRequest( lastWord );
        } else {
          this.autocompletionList.hide();
        }
    }
  },

  onKeyDown : function( e ) {

    if ( ! e ) {
      e = window.event;
    }

    switch( e.keyCode ) {
      case  9: // tab key
      case 13: // return key
        if ( this.autocompletionList.isVisible() ) {

          if ( e.preventDefault ) {
            e.preventDefault();
            e.stopPropagation();
          } else {
            e.returnValue = false;
          }

          this.autocompletionList.appendSelectedTextToTextfield();

          return false;
        }
    }
  },

  onMouseOver : function( e ) {

    if ( ! e ) {
      e = window.event;
    }

    target = ( e.srcElement || e.target );

    this.autocompletionList.select( target.index );
  },

  onMouseDown : function( e ) {
    this.autocompletionList.appendSelectedTextToTextfield();
  },

  hide : function() {
    this.element.style.visibility = 'hidden';
  },

  show : function() {
    this.element.style.visibility = 'visible';
  },

  isVisible : function() {
    return this.element.style.visibility == 'visible';
  },

  setData : function( newData ) {

    this.data = newData;

    for ( i = 0, n = this.listItems.length ; i < n ; ++i ) {
      this.element.removeChild( this.listItems[ i ] );
    }
    this.listItems = new Array();

    for ( i = 0, n = this.data.length ; i < n ; ++i ) {
      this.listItems[ i ] = document.createElement( 'li' );
      var text = document.createTextNode( this.data[ i ] );
      this.listItems[ i ].appendChild( text );

      this.listItems[ i ].index = i;
      this.listItems[ i ].onmousedown = this.onMouseDown;
      this.listItems[ i ].onmouseover = this.onMouseOver;
      this.listItems[ i ].autocompletionList = this;

      this.element.appendChild( this.listItems[ i ] );
    }

    if ( this.data.length > 1 ) {
      this.selectedIndex = 0;
      this.listItems[ 0 ].className = 'selected';
      this.show();
    } else {
      this.selectedIndex = -1;
      this.hide();
    }
  },

  select : function( index ) {
    if ( 0 <= this.selectedIndex && this.selectedIndex < this.data.length) {
      this.listItems[ this.selectedIndex ].className = '';
    }
    if ( 0 <= index && index < this.data.length ) {
      this.listItems[ index ].className = 'selected';
      this.selectedIndex = index;
    }
  },

  selectNext : function() {
    if ( this.data.length > 0 ) {
      var index = this.selectedIndex + 1;
      index %= this.data.length;
      this.select( index );
    }
  },

  selectPrevious : function() {
    if ( this.data.length > 0 ) {
      var index = this.selectedIndex - 1 + this.data.length;
      index %= this.data.length;
      this.select( index );
    }
  },

  appendSelectedTextToTextfield : function() {

    if ( 0 <= this.selectedIndex && this.selectedIndex < this.data.length ) {

      var words = this.textfield.value.split( ", " );

      this.textfield.value = "";
      for ( i = 0 ; i < words.length-1 ; ++i ) {
        this.textfield.value += words[ i ] + ", ";
      }
      this.textfield.value += this.data[ this.selectedIndex ];

      var end = this.textfield.value.length;
      this.textfield.setSelectionRange( end, end );

      this.hide();
    }
  },

  sendRequest : function( requestString ) {

    autocompletionList = this;

    httpRequest.abort();  

    httpRequest.onreadystatechange = function() {
      if ( httpRequest.readyState == 4 ) {

        response = httpRequest.responseText.split( '|' );

        autocompletionList.setData( response );
      }
    };

    httpRequest.open('GET', this.processingPage + requestString, true);

    httpRequest.send(null);
  }
}