// Local autocompleter that uses DWR to update the local array
// Need to try and abstract the dwr part more
// func: the function that provides the array
// formatter: the function that formats the data for display
LocalAutocompleter = Class.create();
LocalAutocompleter.prototype = Object.extend(new Autocompleter.Base(), {
  initialize: function( element, update, func, formatter, options )
  {
    // Check for supported browser
    if ( !this.isSupportedBrowser() )
      return;

    // Attach the div to hold the auto suggest results
    // Attach a div to the element
    // set the div class to 'auto_complete' and id to 'leaving_from_auto_complete'
    TravelocityJsUtils.attachDiv(element, 'auto_complete', update);

    this.baseInitialize(element, update, options);
    this.func = func;
    this.formatter = formatter;
    this.options.array = [ ];
    this.options.onComplete = this.onComplete.bind(this);
    this.options.selector = this.selector.bind(this);
    this.previousToken = "";
    this.previousBackground = "";
  },

  getUpdatedChoices: function()
  {

    var currentToken = this.getToken();
    var previousToken = this.previousToken;

    // If the current entry is a partial of the previous do not go for an update
    if ( currentToken.indexOf(previousToken) == 0 && this.options.array.length > 0 )
      this.updateChoices(this.options.selector(this));
    else
      this.func(this.getToken(), this.options.onComplete);
  },

  onComplete: function( data )
  {
    var formattedData;

    if ( data != null )
      formattedData = this.formatter(data, this.getToken());

    this.options.array = [ ];
    this.previousToken = this.getToken();

    if ( formattedData != null )
      this.options.array = formattedData;

    this.updateChoices(this.options.selector(this));
  },

  selector: function( instance )
  {
    var ret = [];
    // Beginning matches
    var partial = [];
    // Inside matches
    var entry = instance.getToken();
    var count = 0;

    for ( var i = 0; i < instance.options.array.length && ret.length < instance.options.choices; i++ )
    {
      var elem = instance.options.array[i];
      var elemText = elem.stripTags();
      var foundPos = instance.options.ignoreCase ?
                     elemText.toLowerCase().indexOf(entry.toLowerCase()) :
                     elemText.indexOf(entry);

      while ( foundPos != -1 )
      {
        if ( foundPos == 0 && elem.length != entry.length )
        {
          ret.push("<li>" + elem + "</li>");
          //          ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
          //            elem.substr(entry.length) + "</li>");
          break;
        }
        else if ( entry.length >= instance.options.partialChars && instance.options.partialSearch && foundPos != -1 )
        {
          if ( instance.options.fullSearch || /\s/.test(elem.substr(foundPos - 1, 1)) )
          {
            ret.push("<li>" + elem + "</li>");
            //            partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
            //              elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
            //              foundPos + entry.length) + "</li>");
            break;
          }
        }

        foundPos = instance.options.ignoreCase ?
                   elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
                   elem.indexOf(entry, foundPos + 1);

      }
    }
    if ( partial.length )
      ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))

    return "<ul>" + ret.join('') + "</ul>";
  },
  isSupportedBrowser: function ()
  {
    var supported = false;

    try
    {
      if ( browser.isIE6up )
        supported = true;

      if ( browser.isGecko && browser.geckoVersion >= 20040804 )
        supported = true;

      if ( browser.isSafari && ( ( browser.versionMajor == 1 && browser.versionMinor > 1) || browser.versionMajor > 1) )
        supported = true;

    }
    catch ( e )
    {
      supported = false;
    }
    return supported;
  },
// Override and modify KEY_TAB behavior
  onKeyPress: function( event )
  {
    if ( this.active )
      switch ( event.keyCode )
        {
        case Event.KEY_TAB:
          this.selectEntry();
          this.hide();
          event.cancelBubble = false;
          event.returnValue = true;
          return;
        case Event.KEY_RETURN:
          this.selectEntry();
          Event.stop(event);
        case Event.KEY_ESC:
          this.hide();
          this.active = false;
          Event.stop(event);
          return;
        case Event.KEY_LEFT:
        case Event.KEY_RIGHT:
          return;
        case Event.KEY_UP:
          this.markPrevious();
          this.render();
          if ( navigator.appVersion.indexOf('AppleWebKit') > 0 ) Event.stop(event);
          return;
        case Event.KEY_DOWN:
          this.markNext();
          this.render();
          if ( navigator.appVersion.indexOf('AppleWebKit') > 0 ) Event.stop(event);
          return;
      }
    else
      if ( event.keyCode == Event.KEY_TAB || event.keyCode == Event.KEY_RETURN )
        return;

    this.changed = true;
    this.hasFocus = true;

    if ( this.observer ) clearTimeout(this.observer);
    this.observer = setTimeout(this.onObserverEvent.bind(this), this.options.frequency * 1000);
  }
});