/**
 * 
 * @fileoverview js/plugins
 * @description autocomplete<br />
 *  
 * @author bKarolyi 
 */

classes.autocomplete_data_class = function()
{
  //handle stored data
}

classes.autocomplete_data_class.prototype = 
{
  autocomplete_unit_handler_class: null,
  
  data: [],
  
  searched_string: "",
  
  selected_name: null,
  
  selected_id: null,
  
  selected_row: null,
  
  
  
  construct: function( autocomplete_unit_handler_class )
  {
    this.autocomplete_unit_handler_class = autocomplete_unit_handler_class;
    this.searched_string = "";
    
    return true;
  },
  
  set: function( data )
  {
    this.data = data;
    
    return true;
  },
  
  reset: function()
  {
    this.selected_id = "";
    this.selected_name = "";
    this.selected_row = null;
    
    return true;
  },
  
  getDataByRow: function( row )
  {
    for ( i_data = 0; i_data < this.data.length; i_data++ )
    {
      var act_data = this.data[ i_data ];
      if ( act_data.row == row )
      {
        return act_data;
      }
    }
    
    return false;
  },
  
  isBlocked: function( data )
  {
    if ( typeof data.blocked == "undefined" )
    {
      return false;
    }
    
    return data.blocked;
  }
}

classes.autocomplete_texture_class = function()
{
  //for handle texture
}

classes.autocomplete_texture_class.prototype = 
{
  container_el: null,
  
  input_el: null,
  
  list_box: null,
  
  list_ul: null,
  
  iframe: null,
  
  scroll_handler_class: null,
  
  data_handler_class: null,
  
  autocomplete_unit_handler_class: null,
  
  setScrollHandler: function()
  {
    if ( !this.scroll_handler_class )
    {
      this.scroll_handler_class = new classes.autocomplete_scroll_handler_class();
      this.scroll_handler_class.texture_handler = this;
      this.scroll_handler_class.autocomplete_unit_handler_class = this.autocomplete_unit_handler_class;
      this.scroll_handler_class.construct();
      
    }
    
    return true;
  },

  construct: function( autocomplete_unit_handler_class )
  {
    if ( !Dom.get( "n_autocompleteresultswrap" ) )
    {
      return false;
    }
    
    this.autocomplete_unit_handler_class = autocomplete_unit_handler_class;
    this.data_handler_class = null;
    this.scroll_handler_class = null;
    
    this.container_el = Dom.get( "n_autocompleteresultswrap" ).cloneNode( true );
    this.container_el.id += "_" + this.autocomplete_unit_handler_class.id;
    document.body.appendChild( this.container_el );
    
    this.input_el = this.autocomplete_unit_handler_class.el;
    
    //temporary hide prototype to acces clone ids
    var orig_results_wrap = Dom.get( "n_autocompleteresultswrap" );
    var wrap_temp = Dom.get( "n_autocompleteresultswrap" ).cloneNode( true );
    orig_results_wrap.parentNode.removeChild( orig_results_wrap );
    
    this.setScrollHandler();
    
    this.list_box = $( "#n_autocompleteresults", null, true );
    this.list_box.id += "_" + this.autocomplete_unit_handler_class.id;
    
    this.list_ul = $( "#n_autocompleteresultlist", null, true );
    this.list_ul.id += "_" + this.autocomplete_unit_handler_class.id;
    
    //place back original autocomplete box
    document.body.appendChild( wrap_temp )
    
    if ( ie6 ) 
    {
      this.iframe = document.createElement("iframe");
      this.iframe.style.position = "absolute";
      this.iframe.style.zIndex = "-1";
      this.iframe.style.left = "0px";
      this.iframe.style.top = "0px";
      this.iframe.style.height = "0px";
      this.iframe.style.width = "0px";
      Dom.insertBefore(this.iframe, this.list_box);
    }
    
    return true;
  },
  
  
  //events
  setEvents: function()
  {
    
  },
  
  setListEvents: function( row, data )
  {
    Event.on( row, "mouseover", function( e ){
      var target = Event.getTarget( e );
      if ( target.nodeName.toLowerCase() == "span" ) 
      {
        return false;
      }
      
      this.highlightRow( target );
    }, null, this );

    Event.on( row, "mousedown", function( e ){
      var row_el = Event.getTarget( e );
      
      if ( row_el.nodeName.toLowerCase() != "li" )
      {
        row_el = Dom.getAncestorByTagName( row_el, "li" );
      }
      
      var act_data = this.data_handler_class.getDataByRow( row_el );
      if ( this.data_handler_class.isBlocked( act_data ) )
      {
        Event.stopEvent( e );
        return false;
      }
      
      this.selectRow( row_el );
      return true;
      
      var li = Event.getTarget( e );
      if ( this.input_field )
      {
        this.input_field.value = payload.name;
      }
      if ( this.hidden_el )
      {
        this.hidden_el.value = payload.id;
      }
      Event.stopEvent( e );
      this.hideContainer();
      //todo - showtruefeedback - kell? kell, de nem ide, hanem a select után
      if ( this.afterMouseDown )
      {
        this.afterMouseDown( payload );
      }
    }, null, this );
    
    return false;
    
    
    //todo ez nem kell ??? 
    Event.on( row, "mouseout", function( e ){
      //mozilla 2.0.0.3 and up bug - anonymous-div class appears
      
      try
      {
        Event.getRelatedTarget( e ).className;
      }
      catch( e )
      {
        return false;
      }
      
      if ( Event.getRelatedTarget( e ).nodeName.toLowerCase() == "li" )
      {
        this.deSelectRow( Event.getTarget( e ) );
      }
    }, null, this );
  },
  
  
  //visibility
  show: function()
  {
    Dom.setStyle( this.list_box, "height", "auto" );

    var el_top = Dom.getY( this.input_el );
    var el_left = Dom.getX( this.input_el );
    var el_height = parseInt( this.input_el.offsetHeight );
    var el_width = parseInt( this.input_el.offsetWidth );
    var container_top = parseInt( el_top ) + parseInt( el_height );
    
    //increases container width
    this.container_el.style.width = "";
    nw.show( this.container_el );

    var container_width = this.container_el.offsetWidth;
    if ( container_width < el_width )
    {
      this.container_el.style.width = el_width + "px";
    }
    
    //solved temporally - for message_compose
    if ( el_width < 10 )
    {
      this.container_el.style.width = "";
    }
    
    Dom.setX( this.container_el, el_left );
    Dom.setY( this.container_el, el_top+el_height );
    
    var list_box_height = this.list_box.offsetHeight;
    list_box_height = ( list_box_height > 131 ) ? 131 : list_box_height;
    Dom.setStyle( this.list_box, "height", list_box_height + "px" );
    
    if ( ie6 )
    {
      this.iframe.style.height = list_box_height + "px";
      this.iframe.style.width = el_width + "px";
    }
    
    this.alignContainer( el_left, el_width );
    
    this.scroll_handler_class.set();
    
    return true;
  },
  
  alignContainer: function( input_left, el_width )
  {
    var is_in_rightside = false;
    if ( input_left > Dom.getDocumentWidth()/2 )
    {
      is_in_rightside = true;
    }
    
    if ( !is_in_rightside )
    {
      return true;
    }
    
    var container_left = Dom.getX( this.container_el );
    Dom.setX( this.container_el, 0 );
    var container_width = this.container_el.offsetWidth;
    var difference = container_width - el_width;
    Dom.setX( this.container_el, container_left - difference );
    
    return true;
  },
  
  hide: function()
  {
    nw.hide( this.container_el );
    
    if ( ie6 )
    {
      this.iframe.style.height = "0px";
      this.iframe.style.width = "0px";
    }
    
    return true;
  },
  
  
  //handle list
  addRow: function( data )
  {
    var text = data.name;
    var id = data.id;
    
    var first_index = this.replaceText( text );
    if ( first_index != -1 )
    {
      text = text.substr( 0, first_index + this.data_handler_class.searched_string.length ) + "</span>" + text.substr( first_index + this.data_handler_class.searched_string.length, text.length );
      text = text.substr( 0, first_index ) + "<span>" + text.substr( first_index, text.length );
    }
    var list_row = document.createElement( "li" );
    if ( this.data_handler_class.isBlocked( data ) )
    {
      Dom.addClass( list_row, "n_passive" );
    }
    
    list_row.innerHTML = text;
    this.list_ul.appendChild( list_row );
    
    this.setListEvents( list_row, data );
    
    return list_row;
  },
  
  setEmptyList: function()
  {
    this.clearList();
    
    var list_row = document.createElement( "li" );
    list_row.innerHTML = __( "Nincs találat" );
    this.list_ul.appendChild( list_row );
    this.highlightRow( list_row );
    
    Event.on( list_row, "mousedown", function( e ){
      Event.stopEvent( e );
    }, null, this );
    
    nw.hide( this.scroll_handler_class.scroller );
    return true;
  },
  
  clearList: function()
  {
    this.list_ul.innerHTML = "";
    this.data_handler_class.reset();
    
    return true;
  },
  
  setRows: function()
  {
    if ( this.data_handler_class.data.length == 0 )
    {
      this.setEmptyList();
      return true;
    }
    
    this.clearList();
    
    for ( i_data = 0; i_data < this.data_handler_class.data.length; i_data++ )
    {
      var act_data = this.data_handler_class.data[ i_data ];
      
      var act_row = this.addRow( act_data );
      act_data.row = act_row;
    }
    this.highlightFirst();
    
    return true;
  },
  
  
  //selection
  selectRow: function( row )
  {
    if ( !row )
    {
      return false;
    }
    var act_data = this.data_handler_class.getDataByRow( row );
    
    //if there is no result
    if ( !act_data || act_data.length == 0 )
    {
      this.autocomplete_unit_handler_class.el.value = "";
      
      //autocomplete feedback handler
      if ( this.autocomplete_unit_handler_class.country_select_el )
      {
        errorHandlers.showTrueFeedback( this.autocomplete_unit_handler_class.el.id );
      }
      
      if ( this.autocomplete_unit_handler_class.hidden_el )
      {
        this.autocomplete_unit_handler_class.hidden_el.value = "";
      }
      
      return false;
    }
    
    //set select data
    this.data_handler_class.selected_name = act_data.name;
    this.data_handler_class.selected_id = act_data.id;
    this.data_handler_class.selected_row = row;
    
    this.highlightRow( row );
    
    //set input, hidden elements value
    this.autocomplete_unit_handler_class.el.value = act_data.name;
    
    //autocomplete feedback handler
    if ( this.autocomplete_unit_handler_class.country_select_el )
    {
      errorHandlers.showTrueFeedback( this.autocomplete_unit_handler_class.el.id );
    }
    
    //sets hidden value
    if ( this.autocomplete_unit_handler_class.hidden_el )
    {
      this.autocomplete_unit_handler_class.hidden_el.value = act_data.id;
    }
    
    
    return true;
  },
  
  highlightRow: function( row )
  {
    var act_data = this.data_handler_class.getDataByRow( row );
      
    if ( this.data_handler_class.isBlocked( act_data ) )
    {
      return false;
    }
    var rows = $( "LI", this.list_ul );
    Dom.removeClass( rows, "n_selectedrow" );
    
    Dom.addClass( row, "n_selectedrow" );
    
    //scroll the list
    this.scroll_handler_class.setVisibleAreaToHighlighted();
    
    return true;
  },
  
  highlightFirst: function()
  {
    var first_row = $( "LI", this.list_ul, true );
    this.highlightRow( first_row );
    
    return true;
  },
  
  highlightSelected: function()
  {
    if ( this.data_handler_class.selected_row )
    {
      this.highlightRow( this.data_handler_class.selected_row );
    }
    
    return true;
  },
  
  selectHighlighted: function()
  {
    var highlighted_row = $( ".n_selectedrow", this.list_ul, true );
    if ( !highlighted_row )
    {
      return false;
    }
    
    this.selectRow( highlighted_row );
    
    return true;
  },
  
  //other
  replaceText: function( text )
  {
    var str = this.data_handler_class.searched_string;

    var first_index = 0;
    var last_index = 0;
    var temp_str = '';
    var temp_text = '';
    str = str.toLowerCase();
    text = text.toLowerCase();

    for ( i_letter = 0; i_letter < str.length; i_letter++ )
    {
      var letter = "";
      switch ( str.charAt( i_letter ) )
      {
        case "ö":
          letter = "o";
          break;
        case "ü":
          letter = "u";
          break;
        case "ó":
          letter = "o";
          break;
        case "ő":
          letter = "o";
          break;
        case "ú":
          letter = "u";
          break;
        case "é":
          letter = "e";
          break;
        case "á":
          letter = "a";
          break;
        case "ű":
          letter = "u";
          break;
        case "í":
          letter = "i";
          break;
        default:
          letter = str.charAt( i_letter );
      }

      temp_str = temp_str+letter;
    }
    
    for ( i_letter = 0; i_letter < text.length; i_letter++ )
    {
      var letter = "";
      
      switch ( text.charAt( i_letter ) )
      {
        case "ö":
          letter = "o";
          break;
        case "ü":
          letter = "u";
          break;
        case "ó":
          letter = "o";
          break;
        case "ő":
          letter = "o";
          break;
        case "ú":
          letter = "u";
          break;
        case "é":
          letter = "e";
          break;
        case "á":
          letter = "a";
          break;
        case "ű":
          letter = "u";
          break;
        case "í":
          letter = "i";
          break;
        default:
          letter = text.charAt( i_letter );
      }

      temp_text = temp_text+letter;
    }
    return temp_text.indexOf( temp_str );
  }
}

classes.autocomplete_scroll_handler_class = function()
{
  //shift, scrollbar
}

classes.autocomplete_scroll_handler_class.prototype =
{
  texture_handler: null,
  
  autocomplete_unit_handler_class: null,
  
  data_handler_class: null,
  
  scroller: null,
  
  top_arrow: null,
  
  bottom_arrow: null,
  
  interval: null,
  
  construct: function()
  {
    this.interval = null;
    this.data_handler_class = null;
    
    this.scroller = $( "#n_autocompletescroller", null, true );
    this.scroller.id += "_" + this.autocomplete_unit_handler_class.id;
    
    this.top_arrow = $( "#n_scrollup", null, true );
    this.top_arrow.id += "_" + this.autocomplete_unit_handler_class.id;
    
    this.bottom_arrow = $( "#n_scrolldown", null, true );
    this.bottom_arrow.id += "_" + this.autocomplete_unit_handler_class.id;
    
    this.bar = $( "#n_autocompletescrollbar", null, true );
    this.bar.id += "_" + this.autocomplete_unit_handler_class.id;
    
    this.setEvents();
    
    return true;
  },
  
  set: function()
  {
    if ( this.data_handler_class.data.length <= 6 ) 
    {
      Dom.addClass( this.scroller, "n_invisible" );
      Dom.setStyle( this.scroller, "z-index", "-1");
    }
    else
    {
      Dom.setStyle( this.scroller, "z-index", "");
      Dom.removeClass( this.scroller, "n_invisible" );
      this.reset();
    }
  },
  
  setEvents: function()
  {
    //arrows
    Event.on( this.top_arrow, "mousedown", function( e )
    {
      this.scrollUp();
      var act_obj = this;
      this.interval = setInterval( function() 
        {
          act_obj.scrollUp.call( act_obj );
        }, 300 );
      this.mouse_downed = true;
    }, null, this );
    
    Event.on( this.top_arrow, "mouseup", function( e )
    {
      clearInterval( this.interval );
      this.mouse_downed = false;
    }, null, this );

    Event.on( this.top_arrow, "mouseout", function( e )
    {
      clearInterval( this.interval );
    }, null, this );
    
    Event.on( this.bottom_arrow, "mousedown", function( e )
    {
      this.scrollDown();
      var act_obj = this;
      this.interval = setInterval( function() 
        {
          act_obj.scrollDown.call( act_obj );
        }, 300 );
      this.mouse_downed = true;
    }, null, this );
    
    Event.on( this.bottom_arrow, "mouseup", function( e )
    {
      clearInterval( this.interval );
      this.mouse_downed = false;
    }, null, this );
    
    Event.on( this.bottom_arrow, "mouseout", function( e )
    {
      clearInterval( this.interval );
    }, null, this );
    
    
    
    //bar
    Event.on( document.body, "mousedown", function( e )
    {
      e = Event.getEvent( e );
      var target = Event.getTarget( e );
      if ( target.id.indexOf( "n_autocompletescrollbar" ) != -1 || target.id.indexOf( "n_autocompletescroller" ) != -1 )
      {
        Event.stopEvent( e );
        this.last_y = Event.getPageY( e );
        this.orig_bar_top = parseInt( Dom.getStyle( this.bar, "top" ) );
        this.act_bar_top = this.orig_bar_top;
        this.orig_ul_top = parseInt( Dom.getStyle( this.texture_handler.list_ul, "margin-top" ) );
        
        if ( target == this.scroller )
        {
          var a = Dom.getXY( this.scroller )[1] + 16;
          this.last_y = a;
          this.orig_bar_top = 16;
          this.orig_ul_top = 0;
          this.mouse_downed = true;
          this.move( e );
        }
        
        Dom.addClass( this.bar, "n_active" );
        this.mouse_downed = true;
      }
    }, null, this );
    
    Event.on( document.body, "mouseup", function( e )
    {
      var target = Event.getTarget( e );
      
      if ( this.mouse_downed )
      {
        this.round();
        Dom.removeClass( this.bar, "n_active" );
      }
      
      this.mouse_downed = false;
    }, null, this );
    
    Event.on( document.body, "mousemove", function( e )
    {
      if ( this.mouse_downed )
      {
        this.move( e );
      }
    }, null, this );
    
    
    if ( ff )
    {
      Event.on( document.body, 'DOMMouseScroll', this.scrollOnMouseWheel, null, this );
    }
    else
    {
      Event.on( document.body, 'mousewheel', this.scrollOnMouseWheel, null, this );
    }
  },
  
  
  
  scrollOnMouseWheel: function( e )
  {
    var event = Event.getEvent( e );
    
    if ( !nw.isVisible( this.texture_handler.container_el ) )
    {
      return true;
    }

    var delta = 0;
    if ( event.wheelDelta ) /* IE/Opera. */
    {
      delta = event.wheelDelta/120;
    } 
    else if ( event.detail ) /* Mozilla case. */
    {            
      delta = -event.detail/3;
    }

    var target = Event.getTarget( event );
    var pointer_in_autocomplete = Dom.isAncestor( this.texture_handler.container_el, target );
    if ( delta && pointer_in_autocomplete )
    {
      Event.stopEvent( event );
      if ( delta > 0 )
      {
        this.scrollUp();
      }
      else
      {
        this.scrollDown();
      }
      
      return false;
    }
    else
    {
      return true;
    }
  },
  
  scrollUp: function()
  {
    var highlighted_row = $( ".n_selectedrow", this.texture_handler.list_ul, true );
    var highlighted_data = this.data_handler_class.getDataByRow( highlighted_row );
    var data_index = nw.indexOf( highlighted_data, this.data_handler_class.data );
    if ( data_index == 0 )
    {
      return false;
    }
    
    this.texture_handler.highlightRow( this.data_handler_class.data[ data_index - 1 ].row );
    
    this.scroll();
    
    return true;
  },
  
  scrollDown: function()
  {
    var highlighted_row = $( ".n_selectedrow", this.texture_handler.list_ul, true );
    var highlighted_data = this.data_handler_class.getDataByRow( highlighted_row );
    var data_index = nw.indexOf( highlighted_data, this.data_handler_class.data );
    if ( this.data_handler_class.data.length == data_index + 1 )
    {
      return false;
    }
    
    this.texture_handler.highlightRow( this.data_handler_class.data[ data_index + 1 ].row );
    
    this.scroll();
    
    return true;
  },
  
  setVisibleAreaToHighlighted: function()
  {
    var highlighted_row = $( ".n_selectedrow", this.texture_handler.list_ul, true );
    var rows = $( "LI", this.texture_handler.list_ul );
    var highlighted_row_index = nw.indexOf( highlighted_row, rows );
    
    var top_margin = parseInt( Dom.getStyle( this.texture_handler.list_ul, "margin-top" ) );
    var row_height = 22;
    var top_row_num = -top_margin / row_height;
    
    //bottom
    if ( highlighted_row_index - top_row_num >= 6 )
    {
      var multiplier = - highlighted_row_index + 5;
      var new_top_margin = multiplier * row_height;
      Dom.setStyle( this.texture_handler.list_ul, "margin-top", new_top_margin + "px" );
    }
    else if ( highlighted_row_index < top_row_num )
    {
      var multiplier = - highlighted_row_index;
      var new_top_margin = multiplier * row_height;
      Dom.setStyle( this.texture_handler.list_ul, "margin-top", new_top_margin + "px" );
    }
    
    return true;
  },
  
  
  //scrollbar
  bar: null,
  
  going_up: true,
  
  mouse_downed: false,
  
  scrollbar_height: 99,
  
  last_y: 0,
  
  act_bar_top: 0,
  
  modified_ul_top: 0,
  
  orig_bar_top: 0,
  
  orig_ul_top: 0,
  
  computeHeight: function()
  {
    if ( this.data_handler_class.data.length == 0 )
    {
      return false;
    }
    var height = ( 6 / this.data_handler_class.data.length ) * 99;
    return height;
  },
  
  computeTop: function()
  {
    var top = parseInt( Dom.getStyle( this.texture_handler.list_ul, "margin-top" ) );
    var total_num = this.data_handler_class.data.length;
    var unit = 99 / total_num;
    var top_num = -( top / 22 ) * unit + 16;
    return top_num;
  },
  
  move: function( e )
  {
    if ( this.mouse_downed === true )
    {
      var diff = Event.getPageY( e ) - this.last_y;
      var bar_top = this.orig_bar_top + diff;
      if ( bar_top < 16 || bar_top > 99 - this.computeHeight() + 16 )
      {
        return true;
      }
      
      this.going_up = ( this.act_bar_top <= bar_top ) ? true : false;
      
      this.act_bar_top = bar_top;
      var total_num = this.data_handler_class.data.length;
      var unit = 99 / total_num;
      
      Dom.setStyle( this.bar, "top", bar_top + "px" );
      var ul_top = ( ( bar_top - 16 ) / unit ) * -22;
      this.modified_ul_top = ul_top;
      Dom.setStyle( this.texture_handler.list_ul, "margin-top", ul_top + "px" );
    }
  },
  
  reset: function()
  {
    Dom.setStyle( this.bar, "height", this.computeHeight() + "px" );
    
    return true;
  },
  
  round: function()
  {
    var ceil = Math.ceil( this.modified_ul_top );
    var diff = ceil % 22;
    var new_ul_top;
    var positive = ceil > 0;
    if ( Math.abs( diff ) <= 11 )
    {
      if ( positive )
      {
        new_ul_top = ceil - diff;
      }
      else
      {
        new_ul_top = ceil - diff;
      }
    }
    else
    {
      if ( positive )
      {
        new_ul_top = ceil - diff + 22;
      }
      else
      {
        new_ul_top = ceil - diff - 22;
      }
    }
    
    Dom.setStyle( this.texture_handler.list_ul, "margin-top", new_ul_top + "px" );
    this.scroll();
  },
  
  scroll: function()
  {
    if ( !Dom.get( "n_autocompletescrollbar" ) )
    {
      return false;
    }
    var top = this.computeTop();
    Dom.setStyle( this.bar, "top", top + "px" );
  }
}

classes.autocomplete_unit_class = function()
{

}

classes.autocomplete_unit_class.prototype =
{
  id: null,
  
  el: null,
  
  has_focus: false,
  
  //config
  url: "",
  
  delay_obj: null,
  
  delay: 0,
  
  force_fill: false,
  
  hidden_el: null,
  
  autocomplete_handler_class: null,
  
  texture_handler_class: null,
  
  data_handler_class: null,
  
  setDataHandler: function()
  {
    if ( !this.data_handler_class )
    {
      this.data_handler_class = new classes.autocomplete_data_class();
      this.data_handler_class.construct( this );
    }
    
    return true;
  },
  
  setTextureHandler: function()
  {
    if ( !this.texture_handler_class )
    {
      this.texture_handler_class = new classes.autocomplete_texture_class();
      this.texture_handler_class.construct( this );
    }
    
    return true;
  },
  
  construct: function( id, config )
  {
    this.id = id;
    this.el = Dom.get( id );
    this.el.setAttribute( "autocomplete", "off" );
    
    this.setTextureHandler();
    this.setDataHandler();
    
    this.texture_handler_class.data_handler_class = this.data_handler_class;
    this.data_handler_class.texture_handler_class = this.texture_handler_class;
    this.texture_handler_class.scroll_handler_class.data_handler_class = this.data_handler_class;
    
    //config
    this.delay = config.delay || 300;
    this.url = config.url;
    this.force_fill = config.force_fill || false;

    this.hidden_el = config.hidden_id ? Dom.get( config.hidden_id ) : null;
    
    this.setEvents();
    
    
    //set ajax
    this.ajax_getlist = this.ajax_getlist || new n_ajax_class( this.url, "", this.getListCallback, null, "post" );
    this.ajax_getlist.handleFailure = this.getListFailure;
    this.ajax_getlist.indicator_is_disabled = true;
    
    this.collateralConstruct( config );
    return true;
  },
  
  collateralConstruct: function()
  {

  },
  
  setEvents: function()
  {
    Event.on( this.el, "focus", function()
    {
      //show list
      this.onFocus();
    }, null, this )
    
    Event.on( this.el, "blur", function()
    {
      this.onBlur();
    }, null, this )
    
    Event.on( this.el, "keydown", function( e )
    {
      var key = Event.getCharCode( e );
      
      
      if ( key == 13 )
      {
        //enter
        //stop the process if ajax is running
        if ( this.ajax_getlist.transaction )
        {
          Event.stopEvent( e );
          
          return false;
        }
        
        //select if open
        if ( nw.isVisible( this.texture_handler_class.container_el ) )
        {
          this.texture_handler_class.selectHighlighted();
          this.texture_handler_class.hide();
          Event.stopEvent( e );
          
          return false;
        }
        
        //if not open and in input form submited is automatically
        
        return false;
      }
      else if ( key == 27 )
      {
        //27 - esc
        this.texture_handler_class.hide();
        
        return false;
      }
      else if ( key == 8 || key == 46 )
      {
        //27 - esc, 8 - bs, 46 - del
        this.data_handler_class.reset();
        this.texture_handler_class.hide();
        
        return false;
      }
      else if ( key == 38 )
      {
        //up
        this.texture_handler_class.scroll_handler_class.scrollUp();
        Event.stopEvent( e );
        
        return false;
      }
      else if ( key == 40 )
      {
        //down
        this.texture_handler_class.scroll_handler_class.scrollDown();
        Event.stopEvent( e );
        
        return false;
      }
      //preserve alt, ctrl
    }, null, this )
    
    Event.on( this.el, "keyup", function( e )
    {
      var key = Event.getCharCode( e );
      
      if ( key == 13 || key == 27 || key == 38 || key == 40 || key == 39 || key == 37 )
      {
        Event.stopEvent( e );
        
        return true;
      }
      
      //autocomplete feedback handler
      if ( this.country_select_el )
      {
        errorHandlers.hideErrorMsg( this.el.id );
      }
      
      this.getList();
    }, null, this )
  },
  
  onFocus: function()
  {
    this.has_focus = true;
    //if text is too short
    if ( this.el.value.length < 2 )
    {
      return false;
    }
    
    // if initial request is not equal to input value send a request
    if ( this.data_handler_class.searched_string != this.el.value )
    {
      this.getList();
      return true;
    }

    this.texture_handler_class.show();
    
    return true;
  },
  
  onBlur: function()
  {
    this.has_focus = false;
    if ( this.texture_handler_class.scroll_handler_class.mouse_downed )
    {
      var el = this.el;
      setTimeout( function()
      {
        el.focus();
      }, 1 );
      return false;
    }
    
    this.resetState();
    
    return true;
  },
  
  resetState: function()
  {
    //if waiting for ajax
    if ( this.ajax_getlist.transaction )
    {
      this.texture_handler_class.hide();
      
      return true;
    }
    
    //if filling is required
    if ( this.force_fill )
    {
      //if input value is eual to selected value
      if ( this.data_handler_class.selected_name && 
           this.data_handler_class.selected_name == this.el.value )
      {
        this.texture_handler_class.hide();
      }
      else if ( this.data_handler_class.data.length > 0 )
      {
        //if there is result
        this.texture_handler_class.selectHighlighted();
        this.texture_handler_class.hide();
        
        return true;
      }
      else
      {
        //if there is no result
        this.data_handler_class.reset();
        this.el.value = "";
        if ( this.hidden_el )
        {
          this.hidden_el.value = "";
        }
        this.texture_handler_class.hide();
        
        return true;
      }
    }
    else
    {
      //no need to choose
      this.data_handler_class.reset();
      this.texture_handler_class.hide();
    }
    
    return true;
  },
  
  
  
  ajax_getlist: null,
  
  getList: function()
  {
    //if ajax is running abort ajax
    if ( this.ajax_getlist.transaction )
    {
      Connect.abort( this.ajax_getlist.transaction );
      Dom.removeClass( this.el, "n_inputloading" );
    }
    
    //if waiting for delay abort delay
    if ( this.delay_obj )
    {
      clearTimeout( this.delay_obj );
      this.delay_obj = null;
    }
    
    //if value's length lower than 2
    if ( this.el.value.length < 2 )
    {
      return false;
    }
    
    var act_obj = this;
    this.delay_obj = setTimeout( function()
      {
        act_obj.delayedDataSend.call( act_obj );
        return true;
      }, this.delay );
    
    return true;
  },
  
  delayedDataSend: function()
  {
    this.delay_obj = null;
    this.data_handler_class.searched_string = this.el.value;
    this.ajax_getlist.postData = "text=" + this.el.value;
    
    Dom.addClass( this.el, "n_inputloading" );
    this.ajax_getlist.send( this );
    
    return true;
  },
  
  getListCallback: function( o )
  {
    Dom.removeClass( this.el, "n_inputloading" );
    
    if ( !this.ajax_getlist.json_response )
    {
      return false;
    }
    
    var response = this.ajax_getlist.json_response;
    
    //is there a focus on input?
    if ( !this.has_focus )
    {
      this.data_handler_class.set( response );
      this.texture_handler_class.setRows();
      this.resetState();
      
      return true;
    }
    
    this.data_handler_class.set( response );
    this.texture_handler_class.setRows();
    this.texture_handler_class.show();
    
    return false;
  },
  
  getListFailure: function( o )
  {
    Dom.removeClass( this.el, "n_inputloading" );
    
    return true;
  },
  
  setValue: function()
  {
    
  }
}



classes.autocomplete_country_unit_class = function()
{
}

YAHOO.lang.extend( classes.autocomplete_country_unit_class, classes.autocomplete_unit_class, 
  {
    country_select_el: null,
    
    collateralConstruct: function( config )
    {
      this.country_select_el = Dom.get( config.country );
      this.strict_countries = config.strict_countries;
      
      //resets force fill depending on country select value
      if ( nw.indexOf( this.country_select_el.value, this.strict_countries ) != -1 )
      {
        //strict country
        this.force_fill = true;
      }
      else
      {
        //other country
        this.force_fill = false;
      }
      
      //events for country select field
      Event.on( this.country_select_el, "change", function()
      {
        this.data_handler_class.reset();
        this.el.value = "";
        if ( this.hidden_el )
        {
          this.hidden_el.value = "";
        };
        
        if ( nw.indexOf( this.country_select_el.value, this.strict_countries ) != -1 )
        {
          //strict country
          this.force_fill = true;
        }
        else
        {
          //other country
          this.force_fill = false;
        }
      }, null,  this );
      
      return true;
    },
    
    delayedDataSend: function()
    {
      this.delay_obj = null;
      this.data_handler_class.searched_string = this.el.value;
      this.ajax_getlist.postData = "text=" + this.el.value + "&country=" + this.country_select_el.value;
      
      Dom.addClass( this.el, "n_inputloading" );
      this.ajax_getlist.send( this );
      
      return true;
    }
  } );
  


classes.autocomplete_class = function()
{

}

classes.autocomplete_class.prototype =
{
  units: [],
  
  getUnitById: function( id )
  {
    for ( i_unit = 0; i_unit < this.units.length; i_unit++ )
    {
      var act_unit = this.units[ i_unit ];
      if ( id == act_unit.id )
      {
        return act_unit;
      }
    }
    
    return false;
  },
  
  add: function( id, config, unit_class )
  {
    if ( !this.getUnitById( id ) )
    {
      var unit = new unit_class;
      unit.construct( id, config );
      unit.autocomplete_handler_class = this;
      this.units.push( unit );
      return unit;
    }
    else
    {
      return this.getUnitById( id );
    }
  },
  
  blurAll: function()
  {
    for ( i_unit = 0; i_unit < this.units.length; i_unit ++ )
    {
      var act_unit = this.units[ i_unit ];
      act_unit.resetState();
    }
    
    return true;
  },
  
  remove: function( id )
  {
    var unit = this.getUnitById( id );
    
    if ( !unit )
    {
      return false;
    }
    
    var unit_index = nw.indexOf( unit, this.units );
    this.units.splice( unit_index, 1 );
    
    //remove autocomplete list_el
    
    unit.texture_handler_class.container_el.parentNode.removeChild( unit.texture_handler_class.container_el );
    
    delete unit;
    
    //used in the case when input field is no longer in the page. Removing events is no necessary
    
    return true;
  }
}



var n_autocomplete = 
{
  handler_class: null,
  
  initHandlerClass: function()
  {
    this.handler_class = this.handler_class || new classes.autocomplete_class();
    return true;
  },
  
  set: function( id, config )
  {
    this.initHandlerClass();
    Event.onDOMReady( function()
    {
      this.handler_class.add( id, config, classes.autocomplete_unit_class );
    }, null, this );
    
    return true;
  },
  
  countrySet: function( id, config )
  {
    this.initHandlerClass();
    Event.onDOMReady( function()
    {
      this.handler_class.add( id, config, classes.autocomplete_country_unit_class );
    }, null, this );
    
    return true;
  },
  
  blurAll: function()
  {
    this.initHandlerClass();
    this.handler_class.blurAll();
    return true;
  },
  
  remove: function( id )
  {
    this.initHandlerClass();
    
    this.handler_class.remove( id );
    
    return true;
  }
}

