var domcapable = false;
var ajaxcapable = false;
var incapable = false;
var ajax_exclusive_action = "";
var ajax_exclusive_id = 0;

function init() {
    if (document.getElementById && document.getElementsByTagName) {
      var el = document.getElementById("ff_location");
      if (el && el.parentNode && (typeof(el.getAttributeNode) == "function" || typeof(el.getAttributeNode) == "object")) {
        domcapable = true;
      }
    }
    if (window.XMLHttpRequest || window.ActiveXObject) {
      ajaxcapable = true;
    }
	autocompleteinit();
}

function replaceAll(string, searchString, replacementString) {
  if (replacementString.indexOf(searchString) >= 0) {
    // Original string is contained in replacement string; we'll need to do some copying of strings instead.
    var newstring = "";
    var oldpos = 0;
    var pos = string.indexOf(searchString);
    var strlen = searchString.length;
    while (pos >= 0) {
      newstring += string.substring(oldpos, pos)+replacementString;
      oldpos = pos+strlen;
      pos = string.indexOf(searchString, oldpos);
    }
    newstring += string.substring(oldpos, string.length);
    string = newstring;
  }
  else {
    while (string.indexOf(searchString) >= 0) {
      string = string.replace(searchString, replacementString);
    }
  }
  return string;
}

function AJAXInteraction(url, async, callback) {
  var req = newXMLHttpRequest();
  if (req) { req.onreadystatechange = processReqChange; }
  else { callback(""); }
  
  function newXMLHttpRequest() {
    if (window.XMLHttpRequest) { return new XMLHttpRequest(); } 
    else if (window.ActiveXObject) {
      try { return new ActiveXObject("Msxml2.XMLHTTP"); } 
      catch (e) {
        try { return new ActiveXObject("Microsoft.XMLHTTP"); } 
        catch (e2) {}
      }
    }
    return false;
  }

  function processReqChange() {
    if (req.readyState == 4) {
      if (req.status == 200) {
        if (callback) { callback(req.responseXML); }
      }
    }
  }
  
  this.doGet = function() {
    req.open("GET", url, async);
    req.send(null);
    if (!async) {
      processReqChange();
    }
  }
  
  this.doPost = function(data) {
    req.open("POST", url, async);
    req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; Charset=utf-8");
    req.setRequestHeader("Content-length", data.length);
    req.send(data);
    if (!async) {
      processReqChange();
    }
  }
}

function handleReturn(data) {
  try {
    var response = data.documentElement;
    var action   = response.getElementsByTagName("action")[0].firstChild.data;
    var id       = response.getElementsByTagName("id")[0].firstChild.data;
    if (!isNaN(parseInt(id))) {
      id = parseInt(id);
    }
  }
  catch(e) {
    action = "notXML";
    id     = 0;
    response = e;
    ajax_exclusive_action = "";
  }
  if (id == ajax_exclusive_id && (action == ajax_exclusive_action || ajax_exclusive_action == "")) {
    switch (action) {
      case "getsuggestions":
        handleGetSuggestions(id, response);
        break;
      default: 
        ajax_exclusive_action = "";
    }
    ajax_exclusive_id = 0;
    ajax_exclusive_action = "";
  }
}


// ========================================
// === Autocomplete functions.
// ========================================

var sug_input_el; // The locationname input
var sug_suggest_el; // The ul that holds the suggestions
var sug_lat_el; // The latitude input
var sug_lon_el; // The longitude input
var sug_prefix; // The prefix for individual suggestion list-items
var sug_get = ""; // The current value of the input that's kicking off a request
var sug_old = ""; // The previous value of the input
var sug_restrict = true; // A hint that it's worth trying to restrict the suggestions on just large cities

var sug_maxlength = 63; // The maximum string length for which we get suggestions.

var sug_namearrays = new Array(sug_maxlength); // Store previously made suggestions for strings up to length 15

var sug_nameSuggestions = new Array(); // The current suggestions

var sug_current = -1; // Which of the current suggestions is "selected"
var sug_length = 0; // The amount of current suggestions

/* Initialize the autocomplete variables. */
function autocompleteinit() {
    sug_prefix = "sugg_";
	for (var i = 0; i < sug_maxlength; i++) {
		sug_namearrays[i] = sug_nameSuggestions;
	}
}

/* Show the available suggestions, populating the list first if necessary. */
function showSuggestions(populate) {
  if (sug_length > 0) {
    if (populate) {
      for (var i = 0; i < sug_length; i++) {
        document.getElementById(sug_prefix+i).className = "";
        if (sug_nameSuggestions[i]) {
          document.getElementById(sug_prefix+i).innerHTML = replaceAll(replaceAll(sug_nameSuggestions[i], "&", "&amp;"), "<", "&lt;").replace(/\[\[\[(.*)\]\]\]$/, "<span class=\"state\">$1</span>");
        }
        else {
          document.getElementById(sug_prefix+i).innerHTML  = "";
        }
      }
      for (var i = sug_length; i < 10; i++) {
        document.getElementById(sug_prefix+i).className = "hidden";
        document.getElementById(sug_prefix+i).innerHTML = "";
      }
    }
    sug_suggest_el.className = "";
  }
}

/* Hide the available suggestions. */
function hideSuggestions(fromblur) {
  if (sug_current >=0) {
    document.getElementById(sug_prefix + sug_current).className = "";
  }
  sug_current = -1;
  if (fromblur) {
    setTimeout("sug_suggest_el.className = \"hidden\"", 150);
  }
  else {
    sug_suggest_el.className = "hidden";
  }
  return false;
}

/* Fire off an AJAX request to get suggestions based on the current value of the locationname. */
function getSuggestions() {
	sug_input_el = document.getElementById("ff_location");
    sug_suggest_el = document.getElementById("suggestions");
  if (sug_input_el.value.length >= 2 && sug_get != sug_input_el.value) {
    sug_old = sug_get;
    sug_get = sug_input_el.value;
    if (sug_get.length <= sug_old.length || sug_get.substr(0, sug_old.length) != sug_old) {
      // The results of this won't be a subset of an earlier request which resulted in moving the restricting, so start with trying the restricted version again.
      sug_restrict = true;
    }
    if (sug_namearrays[sug_get.length][0] && sug_namearrays[sug_get.length][0].substr(0,sug_get.length) == sug_get) {
      // Use the cached arrays.
      sug_nameSuggestions = sug_namearrays[sug_get.length];
      sug_length = sug_nameSuggestions.length;
      showSuggestions(true);
    }
    else if (ajax_exclusive_action == "") {
      // Perform an AJAX call
      var unique = new Date().getTime();
      var data = "q=" + encodeURIComponent(sug_get) + "&unique=" + unique;
      ajax_exclusive_id = parseInt(unique);
      var important = false;
      var ai = new AJAXInteraction("/ajax/non_session/get_accom_locations.cfm?"+data, !important, function(returndata) { handleReturn(returndata); });
      ai.doGet();
    }
  }
  else if (sug_input_el.value.length == 1) {
    sug_get = sug_input_el.value;
    hideSuggestions(false);
  }
}

/* Handle the returned information on the request for suggestions. */
function handleGetSuggestions(id, data) {
  if (data.getElementsByTagName("q")[0] && data.getElementsByTagName("q")[0].firstChild && 
      (data.getElementsByTagName("q")[0].firstChild.data == sug_get || data.getElementsByTagName("q")[0].firstChild.data == sug_old)) {
    var suggestions = data.getElementsByTagName("suggestion");
    var count = 0;
    var thislength = data.getElementsByTagName("q")[0].firstChild.data.length;
    var sug_temp_name = new Array();
    for (var i = 0; i < suggestions.length; i++) {
      if (suggestions[i].getElementsByTagName("name")[0] && suggestions[i].getElementsByTagName("name")[0].firstChild) {
        sug_temp_name.push(suggestions[i].getElementsByTagName("name")[0].firstChild.data);
        count++;
      }
    }
    if (count > 0 || suggestions.length == 0) {
      sug_namearrays[thislength] = sug_temp_name;
      if (suggestions.length == 0) {
        hideSuggestions();
      }
    }
    if (data.getElementsByTagName("q")[0].firstChild.data == sug_get) {
      sug_nameSuggestions = sug_namearrays[thislength];
      sug_length = count;
      sug_current = -1;
      showSuggestions(true);
    }
  }
}

/* Move one up for the currently selected suggestion. */
function prevSuggestion() {
  if (sug_current >= 0) {
    document.getElementById(sug_prefix + sug_current).className = "";
    --sug_current;
    if (sug_current >=0) {
      document.getElementById(sug_prefix + sug_current).className = "selected";
    }
    else {
      hideSuggestions(false);
    }
    return false;
  }
  return true;
}

/* Move one down for the currently selected suggestion. */
function nextSuggestion() {
  if (sug_current < sug_length-1) {
    if (sug_current >=0) {
      document.getElementById(sug_prefix + sug_current).className = "";
    }
    else {
      showSuggestions(false);
    }
    ++sug_current;
    document.getElementById(sug_prefix + sug_current).className = "selected";
    return false;
  }
  return true;
}

/* Fill in the selected suggestion. */
function pickSuggestion(i) {
  if (i >= 0 && i < sug_length) {
    sug_input_el.value = sug_nameSuggestions[i];
    hideSuggestions(false);
    sug_get = sug_nameSuggestions[i]; // Prevent us from getting suggestions using this just-filled in string.
    return false;
  }
  return true;
}

/* Handle the key-down/key-press events for the autocomplete code. */
function handleKeyDown(ev) {
  if (window.event) {
    ev = window.event;
  }
  if (ev) {
    // IE doesn't do keypresses, only keyup and keydown; so, ignore keydown, unless this is an incapable browser. 
    // Too fragile for my tastes, but probably acceptable given the limited number of times people will hit the autocomplete code.
    if (incapable || ev.type == "keypress") {
      switch(ev.keyCode) {
        case 63232: // UP for Safari
        case 38: // UP
          return prevSuggestion();
          break;
        case 63233: // DOWN for Safari
        case 40: // DOWN
          return nextSuggestion();
          break;
        case 9: // TAB
        case 13: // ENTER
          // Don't allow key down to submit
          if (sug_current >= 0 && sug_current < sug_length) { return false; }
          break;
        case 27: // ESC
          if (sug_current >= 0) { return false; }
          break;
      }
    }
  }
  return true;
}

/* Handle the key-up event for the autocomplete code. */
function handleKeyUp(ev) {
  if (window.event) {
    ev = window.event;
  }
  if (ev) {
    switch(ev.keyCode) {
      case 9: // TAB
      case 13: // ENTER
        return pickSuggestion(sug_current);
        break;
      case 27: // ESC
        return hideSuggestions(false);
        break;
    }
  }
  return true;
}

if (typeof window.addEventListener != "undefined") {
	window.addEventListener('load', init, false);
} else if (typeof document.addEventListener != "undefined") {
	document.addEventListener('load', init, false);
} else if (typeof window.attachEvent != "undefined") {
	window.attachEvent('onload', init);
}
