// function log(what)
//{
//   document.getElementById("dbg").innerHTML += what ;
//}

function TypeAheadControl(list, box, orig, submit, optype, ie6hack)
{
   //
   // Squirrel away the parameters we were given
   //
   this.elementList = list;
   this.textBox = box;
   this.origin = orig;
   this.submit = submit;
   this.optype = optype;
   this.results = 0;
   this.maxResults = 35;
   this.ie6hack = ie6hack;
   var myThis = this;

   //
   // Setup the lowercase names
   //
   var i = 0;
   while (i < list.length) {
     if (null == list[i]) {
        list.length = i;
        break;
     }
     list[i][2] = list[i][0].toLowerCase();
     i++;
   }
   //
   // Set up the "dropDown"
   //
   this.dropDown = document.createElement("div");
   this.dropDown.className = "dropdown";
   this.dropDown.style.visibility = "hidden";
   this.dropDown.style.width = box.offsetWidth;
   this.dropDown.current = -1;
   document.body.appendChild(this.dropDown);

   //
   // mouse listeners for the dropdown box
   //
   this.dropDown.onmouseover = function(event) 
   {
       if (!event) {
          event = window.event;
       }
       target = event.target;
       if (!target) {
          target = event.srcElement;
       }
       myThis.select(target);
   }
   
   this.dropDown.onmousedown = function(event) 
   {
       if (-1 != myThis.dropDown.current) {
          myThis.textBox.value = myThis.results[myThis.dropDown.current][0];
       }
   }

   //
   // Add the listeners to the text box
   //
   this.textBox.onkeyup = function(event) {
     //
     // get window even if needed
     //
     if (!event) {
       event = window.event;
     }
     myThis.handleKeyUp(event);
   }

   this.textBox.onkeydown = function(event) {
     if (!event) {
       event = window.event;
     }

     myThis.handleKeyDown(event);
   }

   this.textBox.onblur = function() {
     myThis.hideDrop();
   }

   this.textBox.onfocus = function() {
     myThis.handleChange();
   }

}
//
// Given a name return the first maxresults, or all possibles
//
TypeAheadControl.prototype.getPossible = function(name) 
{
   var possibles = [];
   var inIndex = 0;
   var outIndex = 0;
   name = name.toLowerCase();
   var strIndex = 0;
   var str;
   var ostr;

   while (outIndex <= this.maxResults && inIndex < this.elementList.length) {
      strIndex = this.elementList[inIndex][2].indexOf(name);
      if (-1 != strIndex) {
         //
         // a hit
         //
         str = this.elementList[inIndex][0];
         possibles[outIndex] = new Array(str, this.elementList[inIndex][1]);
         outIndex ++;
       } else {
         //
         // Check entityId
         strIndex = this.elementList[inIndex][1].indexOf(name);
         if (-1 != strIndex) {
            //
            // a hit
            //
            str = this.elementList[inIndex][0];
            possibles[outIndex] = new Array(str, this.elementList[inIndex][1]);
            outIndex ++;
         }
      }
       inIndex ++;
    }
    return possibles;
}

TypeAheadControl.prototype.handleKeyUp = function(event) {
  var key = event.keyCode;

  if (27 == key) {
     //
     // Escape - clear
     //
     this.textBox.value = "";
     this.handleChange();
  } else if (8 == key || 32 == key || (key >= 46 && key < 112) || key > 123) {
     //
     // Backspace, Space and >=Del to <F1 and > F12
     //
     this.handleChange();
  }
}
 
TypeAheadControl.prototype.handleKeyDown = function(event) {

   var key = event.keyCode;

   if (38 == key) {
      //
      // up arrow
      //
      this.upSelect();

   } else if (40 == key) {
      //
      // down arrow
      //
      this.downSelect();
   }
} 

TypeAheadControl.prototype.hideDrop = function()
{
   var i = 0;
   if (null != this.ie6hack) {
      while (i < this.ie6hack.length) {
         this.ie6hack[i].style.visibility = "visible";
         i++;
      }
   }
   this.dropDown.style.visibility = "hidden";
   this.doUnselected();
}

TypeAheadControl.prototype.showDrop = function()
{
   var i = 0;
   if (null != this.ie6hack) {
      while (i < this.ie6hack.length) {
         this.ie6hack[i].style.visibility = "hidden";
         i++;
      }
   }
   this.dropDown.style.visibility = "visible";
}


TypeAheadControl.prototype.doSelected = function()
{
   this.submit.value="Select";
   this.optype.value = "selection";
}

TypeAheadControl.prototype.doUnselected = function()
{
   this.submit.value="Search";
   
   this.optype.value = "search";
}

TypeAheadControl.prototype.handleChange = function() {

  var val = this.textBox.value;
  var res = this.getPossible(val);


  if (0 == res.length || this.maxResults < res.length) {
     this.hideDrop();
     this.doUnselected();
     this.results = [];
     this.dropDown.current = -1;
  } else {
     this.results = res;
     this.populateDropDown(res);
     if (1 == res.length) {
        this.select(this.dropDown.childNodes[0]);
        this.doSelected();
     } else {
        this.doUnselected();
     }
  }
}

//
// A lot of the stuff below comes from 
// http://www.webreference.com/programming/javascript/ncz/column2
//
// With thanks to Nicholas C Zakas
//
TypeAheadControl.prototype.populateDropDown = function(list)
{
    this.dropDown.innerHTML = "";
    var i = 0;
    var div;
    while (i < list.length) {
      div = document.createElement("div");
      div.appendChild(document.createTextNode(list[i][0]));
//      div.style.zIndex = "1000";
      this.dropDown.appendChild(div);
      i++;
    }
    var off = this.getXY();
    this.dropDown.style.left = off[0] + "px";
    this.dropDown.style.top = off[1] + "px";
    this.showDrop();
}

TypeAheadControl.prototype.getXY = function() 
{

   var node = this.textBox;
   var sumX = 0;
   var sumY = node.offsetHeight;
   
   while(node.tagName != "BODY") {
     sumX += node.offsetLeft;
     sumY += node.offsetTop;
     node = node.offsetParent;
   }
   //
   // And add in the offset for the Body
   //
   sumX += node.offsetLeft;
   sumY += node.offsetTop;

   return [sumX, sumY];
}

TypeAheadControl.prototype.select = function(selected) 
{
    var i = 0;
    var node;
    this.dropDown.current = -1;
    this.doUnselected();
    while (i < this.dropDown.childNodes.length) {
       node = this.dropDown.childNodes[i];
       if (node == selected) {
          //
          // Highlight it
          //
          node.className = "current";
          //
          // turn on the button
          //
	    this.doSelected();
          //
          // setup the cursor
          //
          this.dropDown.current = i;
          //
          // and the value for the Server
          //
          this.origin.value = this.results[i][1];
       } else {
          node.className = "";
       }
       i++;
    }
    this.textBox.focus();
};

TypeAheadControl.prototype.downSelect = function() 
{
    if (this.results.length > 0) {

      if (-1 == this.dropDown.current) {
         //
         // mimic a select()
         //
         this.dropDown.current = 0;
         this.dropDown.childNodes[0].className = "current";
         this.doSelected();
         this.origin.value = this.results[0][1];

      } else if (this.dropDown.current < (this.results.length-1)) {
         //
         // turn off highlight
         //
         this.dropDown.childNodes[this.dropDown.current].className = "";
         //
         // move cursor
         //
         this.dropDown.current++;
         //
         // and "select"
         //
         this.dropDown.childNodes[this.dropDown.current].className = "current";
         this.doSelected();
         this.origin.value = this.results[this.dropDown.current][1];
      }
   }
 }


TypeAheadControl.prototype.upSelect = function() 
{
  if ((this.results.length > 0) &&
      (this.dropDown.current > 0)) {
    
       //
       // turn off highlight
       //
       this.dropDown.childNodes[this.dropDown.current].className = "";
       //
       // move cursor
       //
       this.dropDown.current--;
       //
       // and "select"
       //
       this.dropDown.childNodes[this.dropDown.current].className = "current";
       this.doSelected();
       this.origin.value = this.results[this.dropDown.current][1];
    }
}