// Global variables
var nn4 = (document.layers);
var dom = (document.getElementById);
var iex = (document.all);
var selection = 0;
var objQueryResults = null;
var objInput = null;
var query;
var answers = [];

//Parameters
var _idInput = "SuggestID";
var _idQueryResults = "popup";
var _xQueryResults = "220px";
var _yQueryResults = "322px";
var _bgColor = "#dcdcdc";
var _highLightColor = "#9dccff";

// Initialisation of layers (browser dependant) :
// Create the objQueryResults object
function initializeLayers()
{
  if (dom && (document.getElementById(_idQueryResults))) {
    objQueryResults = document.getElementById(_idQueryResults).style;
    objInput = document.getElementById(_idInput);
  }
  else if (iex && (_idQueryResults)) {
    objQueryResults = _idQueryResults.style;
    objInput = _idInput;
  }
  else if (nn4 && (document.layers[_idQueryResults])) {
    objQueryResults = document.layers[_idQueryResults];
    // Need a method to get objInput here...
    document.captureEvents(Event.MOUSEDOWN|Event.MOUSEMOVE|Event.MOUSEUP);
  }
  if (objQueryResults) {
    objQueryResults.left = _xQueryResults;
    objQueryResults.top = _yQueryResults;
  }
}

// write content of a string in a given layer
function writeLayer(objLayer, idLayer, str)
{
  if (nn4) {
    objLayer.document.write(str);
    objLayer.document.close();
    objLayer.visibility = "visible";
  }
  else if (dom) {
    document.getElementById(idLayer).innerHTML = str;
    objLayer.visibility = "visible";
  }
  else if (iex) {
    document.all[idLayer].innerHTML = str;
    objLayer.visibility = "visible";
  }
}

// @desc: Hides the results layer if it is currently visible.
function hideResults()
{
  objQueryResults.visibility = "hidden";
}

function sendRes(q, jsonStr)
{
  var o = jsonStr.parseJSON();

  for (var i = 0; i < o.length; ++i)
  {
    var title = o[i][0];
    var url = baseUrl + titleToUrl(title)
    if (o[i][2].length > 0) {
      title += " &rarr; " + o[i][2];
    }
    o[i][3] = title;
    o[i][2] = url;
  }
  answers[q] = o;
  selection = 1;
  display(selection);
  // display QueryResults layer
  if (objQueryResults) { display(selection); }
}

// Display query results
function display(selectedLine)
{

  var res = answers[query];
  if (res && res.length > 0)
  {
    selection = selectedLine;
    if (selectedLine > res.length) { selection = res.length; }

    var s = '<div style="font:11px/20px verdana, arial, helvetica, sans-serif; border: 1px dashed black; background-color: ' + _bgColor + '; width: 500px; height: ' + (23 * res.length) + 'px;" >';
    s += '<table cellspacing="0" style="width:100%; ">';

    for (var i = 1; i < 11; ++i) {
      if (i <= res.length)
        {
          if (i == selection)
 	    { s += '<tr id="suggest-' + i + '" style="background-color: ' + _highLightColor + ';">'; }
            else
 	    { s += '<tr id="suggest-' + i + '">'; }
          s += '<td width="450" onMouseMove="display(' + i + ');">'; 
          s += '<a href="' + res[i - 1][2] + '">' + res[i - 1][3] + '</a>';
          s += '</td><td>' + res[i - 1][1] + '</td></tr>';
        }
    }
    s += '</table></div>';
    // display string in layer
    writeLayer(objQueryResults, _idQueryResults, s);
  }
  else { hideResults(); }
}

function changeHighlight(oldId, newId)
{ 
   var res = answers[query];
   if (newId > res.length) { newId = selection = res.length; }   
   if (newId == oldId) {
     return; // nothing to do.
   }
   var oldRow = document.getElementById('suggest-' + oldId);
   if (oldRow) {
     oldRow.style.backgroundColor = _bgColor;
   }
   var newRow = document.getElementById('suggest-' + newId);
   if (newRow) {
     newRow.style.backgroundColor = _highLightColor;
   }
}

function encodeQuery(value)
{
  if (encodeURIComponent) {
    return encodeURIComponent(value);
  }
  if(escape) {
    return escape(value);
  }
}

function webQuery(value, showAutocomplete)
{
  var xmlhttp = getHttp();
  if (xmlhttp) {
    xmlhttp.open("GET", "query.php?query=" + encodeQuery(value),true);
    xmlhttp.onreadystatechange=function()
      {
        if (xmlhttp.readyState==4) {
          sendRes(value, xmlhttp.responseText);
	  if (showAutocomplete) { suggestNextText(value); }
        }
      };
     xmlhttp.send(null);
  }
}

// @desc: Updates the text of the textbox with any autocompletion, and selects the autocompleted text.
function selectRange (oldText, iStart, iLength, newText) {
  // if the text has changed in the interim, then abort any autocompletion.
  if (objInput.value != oldText) {
    return;
  }

  // otherwise, perform autocomplete. Method to use depends on browser.
  // Internet Explorer version:
  if (objInput.createTextRange) {
    // Series of steps to find the current cursor position:
    objInput.focus();
    var oSel = document.selection.createRange();
    var selectionLength = oSel.text.length;
    oSel.moveStart ('character', -objInput.value.length);
    var cursorPos = oSel.text.length - selectionLength;
    // only use autosuggest when we are at the end of the text field.
    if (cursorPos != objInput.value.length) { return; }
    objInput.value = newText;
    var oRange = objInput.createTextRange();
    oRange.moveStart("character", iStart);
    oRange.moveEnd("character", iLength - objInput.value.length);
    oRange.select();
  } 
  // Firefox / Mozilla version:
  else if (objInput.setSelectionRange) {
    // only use autosuggest when we are at the end of the text field.
    if (objInput.selectionStart != objInput.value.length) { return; }
    objInput.value = newText;
    objInput.setSelectionRange(iStart, iLength);
  }
}

// @desc: Returns the MediaWiki article URL for a given article title.
function titleToUrl(title) {
  var chr, url = "";
  for (var i=0; i<title.length; i++) {
     chr = title.charCodeAt(i);
     url += (chr == 32 ? "_" : encodeURI(String.fromCharCode(chr)));
  }
  return url;
}

function suggestNextText(oldText) {
  var res = answers[query];
  if (!res) { return; }
  var start = objInput.value.length;
  // if there is only one result, then fill in the whole field with that.
  if (res.length == 1) {
     selectRange(oldText, start, res[0][0].length, res[0][0]);
  }
  // if there are multiple results, then use the intersection of the first two results.
  else if (res.length > 1) {
     var end, extraText = "";
     for (var i=start; i<=res[0][0].length; i++) {
       if (res[0][0].charAt(i) == res[1][0].charAt(i)) {
         extraText += res[selection][0].charAt(i);
       } else {
         end = i;
         break;
       }
     }
     // only autocomplete if we found something.
     if (extraText.length >= 1) {
       selectRange(oldText, start, end, objInput.value + extraText);
     }
  }
}

function keyDown(e) 
{
  var intKey = (window.Event) ? e.which : e.keyCode;
  var value = objInput.value;

  if (intKey == 40) // Arrow Down
  {
    if (value !== "") {
      selection = selection + 1;
      changeHighlight(selection - 1, selection);
    }
  }
  else if (intKey == 38) // Arrow Up
  {
    if (selection > 1 && value !== "") {
       selection = selection - 1;
       changeHighlight(selection + 1, selection);
    }
  }
  else if (intKey == 13) // enter
  {
    var res = answers[query];
    // Open the first entry in the results, if there is one.
    if (res && res.length > 0) { window.location.href=res[selection - 1][2]; }
    // Otherwise perform a Special:Search on this term.
    else {  window.location.href=baseUrl + "Special:Search/" + titleToUrl(value); }

  }
  // if the search term changed.
  else if (query != value) {
      if (value === "") { hideResults(); }
      else {
        selection = 1;
        query = value;
        // show the autocomplete only if it is a normal character key of some description:
        var showAutocomplete = (intKey == 32 || (intKey > 46 && !(intKey >= 112 && intKey <= 123)));
        // if we already know the answer, use that, otherwise query web site.
        if (answers[query]) { 
          display(selection);
          if (showAutocomplete) { suggestNextText(query); }
        } else { 
          webQuery(value, showAutocomplete);
      }
    }
  }
}

function resize()
{
  var tmp = ((document.body.offsetWidth - 210) / 2 + 210 - 250) + "px";
  objQueryResults.left = tmp;
  objInput.style.left = tmp;
}

function getHttp()
{
  var xmlhttp = false;
  /*@cc_on @*/
  /*@if (@_jscript_version >= 5)
  // JScript gives us Conditional compilation, we can cope with old 
  // IE versions. and security blocked creation of the objects.
  try {
    xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
  } catch (e) {
    try {
      xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    } catch (E) {
      xmlhttp = false;
    }
  }
  @end @*/
  if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
    try {
      xmlhttp = new XMLHttpRequest();
    } catch (e) {
      xmlhttp = false;
    }
  }
  if (!xmlhttp && window.createRequest) 
  {
    try {
      xmlhttp = window.createRequest();
    } catch (e) {
      xmlhttp = false;
    }
  }
  return xmlhttp;
}
initializeLayers();
resize();
window.onresize = resize;
