function CSuggestion(fieldName)
{
	this.fieldName 		= fieldName;
	this.lastRequest 	= '';
	this.timer			= false;
	this.hideTimeOut	= 5000;
	this.showTimeOut    = 100;
	this.searchKey		= '';
	this.selectedIndex	= -1;
	this.showTimer      = false;
	this.AjaxRequest    = false;
}

CSuggestion.prototype = {

    config: function(obj)
	{
		this.searchKey              = obj.searchKey?obj.searchKey:'';
        this.requestUrl             = obj.requestUrl?obj.requestUrl:'';
        
        this.scrollUpId             = obj.scrollUpId?obj.scrollUpId:'';
        this.scrollUp               = obj.scrollUp?obj.scrollUp:'';
        this.scrollDownId           = obj.scrollDownId?obj.scrollDownId:'';
        this.scrollDown             = obj.scrollDown?obj.scrollDown:'';
		this.useHiddens             = obj.useHiddens?true:false;
		this.submitOnWordClick		= obj.submitOnWordClick?false:true;
	},
	
	/*
	* This method provides initialization of the suggestion feature
	*/
	init: function()
	{
		this.objField = $(this.fieldName);
		if (this.objField)
		{
			Event.observe(this.objField, "focus", function(evt){
				var el = Event.element(evt);
				if (el) 
				{
					el.removeClassName("errFieldCss");
				}
			});
			Event.observe(this.objField, "keyup", this.preRequest.bindAsEventListener(this));
            Event.observe(this.objField, "mouseover", this.hideTimerReset.bindAsEventListener(this));
            Event.observe(this.objField, "mouseout", this.hideTimerSet.bindAsEventListener(this));
            
            if ( $('suggestions') )
            {
                var links = $('suggestions').getElementsBySelector('a[rel="deactivate"]');
                links.each(function(el) { el.onclick = function() { return false }; } )
                links.invoke('observe', 'click', this.hideSuggestions.bindAsEventListener(this) );
                links.invoke('observe', 'mouseover', this.hideTimerReset.bindAsEventListener(this) );
                links.invoke('observe', 'mouseout', this.hideTimerSet.bindAsEventListener(this) );
            }
            
            this.objField.setAttribute('autocomplete', 'off');
		}
	},
    
	preRequest: function(evt)
	{
		var srcEl = Event.element(evt);
		var key = evt.which || evt.keyCode;
        
		if (key == Event.KEY_ESC)
        {
            this.hideSuggestions();
			return;
        }

		if (this.AjaxRequest) return;

		if (this.showTimer) clearTimeout(this.showTimer);
		this.showTimer = window.setTimeout(function() {
			this.getStrings(srcEl, key);
		}.bind(this), this.showTimeOut);
	},
	
	/*
	* Sets selectedIndex default value
	*/
	resetSelectedIndex: function()
	{
		this.selectedIndex = -1;
	},

	/*
	* This function provides keys handle
	* @param	{object MouseEvent}	evt
	*/
	getStrings: function(srcEl, key)
	{
		if ( srcEl /*&& srcEl.value != this.lastRequest*/ )
		{
			var keys = [Event.KEY_TAB, Event.KEY_LEFT, Event.KEY_UP, Event.KEY_DOWN, Event.KEY_RIGHT, 13 /*Enter*/];
			//if ( key != 38 && key != 40 && key != 9 )
			if ( (keys.indexOf(key) == -1) )
			{
				//alert(1);
				this.request(this.requestUrl+'?'+this.searchKey+'='+srcEl.value);
				//this.lastRequest = srcEl.value;
				this.resetSelectedIndex();
			}
		}
	},

    scrollRequest: function(evt)
	{
		var el = Event.findElement(evt, 'a');
		if (el)
		{
			this.setLoadingEffect();
			this.hideTimerReset();
			var srcEl = this.objField;
			this.request(this.requestUrl+'?'+this.searchKey+'='+srcEl.value+'&page='+el.rel);
		}
		return false;
	},
	
	setLoadingEffect: function()
	{
		Utils.setLoadingEffect($('suggestions'), 'suggestionsLoadingEffect', 'suggestionsLoadingEffect', {
            'width':$('suggestions').down('div.dropInner').getWidth(),
            'height':$('suggestions').getHeight(),
            'left':Utils.getLeftPos($('suggestions').down('div.dropInner'))
        });
	},
	
	request: function(url)
	{
		//if (this.AjaxRequest) return;
		this.AjaxRequest = new Ajax.Request(url, {
            'onSuccess':this.successLoading.bind(this)
        });
	},
	DrawContainer:function(words, objContainer)
	{
		
			var objContainerInner = objContainer.down('div.dropInner');
            objContainerInner.innerHTML = '';
			
			if ($(this.scrollUpId))
			{
				$(this.scrollUpId).remove();
			}
			
			if ($(this.scrollDownId))
            {
                $(this.scrollDownId).remove();
            }
			
			var word_arr = words[0].getElementsByTagName('word');
            if ( word_arr && word_arr.length )
            {
				/*
				 * top scroll begin
				 */
				var up = words[0].getElementsByTagName('up');
	            if (up && up[0])
	            {
	                if( up[0].firstChild.nodeValue != '0' )
					{
						var objContainerBlock = objContainerInner.up();
						var scrollUpTpl = new Template(this.scrollUp);
						Insertion.Top(objContainerBlock, scrollUpTpl.evaluate({'page':up[0].firstChild.nodeValue}));
						
						var links = $(this.scrollUpId).getElementsBySelector('a');
			            links.each(function(el) { el.onclick = function() { return false }; } )
						links.invoke('observe', 'click', this.scrollRequest.bindAsEventListener(this) );
			            links.invoke('observe', 'mouseover', this.hideTimerReset.bindAsEventListener(this) );
						links.invoke('observe', 'mouseout', this.hideTimerSet.bindAsEventListener(this) );
					}
	            }
				/*
				 * top scroll end
				 */
				
                for (var i = 0; i < word_arr.length; i++ )
                {
                    var word        = document.createElement('A');
					word.href       = '#_';
					word.target     = word_arr[i].getAttribute("id");
					
					Event.observe(word, "mouseover", function(evt) {
                        var target = Event.element(evt);
                        if ( this.selectedIndex != -1 )
                        {
                            var els = objContainerInner.getElementsByTagName('A');
                            for ( var i = 0; i < els.length; i++ )
                                els[i].className = 'out';
                        }
                        this.selectedIndex = target.rel;
                        target.className = 'over';
                    }.bindAsEventListener(this));
					Event.observe(word, "mouseover", this.hideTimerReset.bindAsEventListener(this));
					
					Event.observe(word, "mouseout", this.hideTimerSet.bindAsEventListener(this));
					
					word.onclick = function() { return false; };
					Event.observe(word, "click", function(evt) {
                        var el = Event.element(evt);
                        this.objField.value = el.firstChild.nodeValue;
						
						if (this.useHiddens)
						{
							var hiddens = this.objField.up('form').getInputs("hidden");
	                        hiddens.each(function(v) {
	                            v.value = el.target;
	                        });
						}
						
                        this.hideSuggestions();
						this.objField.focus();
						
						if (interfaceObj && this.submitOnWordClick)
						{
							interfaceObj.submitCharityForm(this.objField.up('form'));
						}
                        return false;
                    }.bindAsEventListener(this));
					
					word.setAttribute('rel',i);

                    word.update(word_arr[i].firstChild.nodeValue);
                    
					Insertion.Bottom(objContainerInner, word);
                }
				/*
                 * bottom scroll begin
                 */
				var down = words[0].getElementsByTagName('down');
	            if (down && down[0])
	            {
	                if ( down[0].firstChild.nodeValue != '0' )
					{
						var objContainerBlock = objContainerInner.up(); 
						var scrollDownTpl = new Template(this.scrollDown);
                        Insertion.Bottom(objContainerBlock, scrollDownTpl.evaluate({'page':down[0].firstChild.nodeValue}));
						
						var links = $(this.scrollDownId).getElementsBySelector('a');
                        links.each(function(el) { el.onclick = function() { return false }; } )
                        links.invoke('observe', 'click', this.scrollRequest.bindAsEventListener(this) );
                        links.invoke('observe', 'mouseover', this.hideTimerReset.bindAsEventListener(this) );
                        links.invoke('observe', 'mouseout', this.hideTimerSet.bindAsEventListener(this) );
					}
	            }
                /*
                 * bottom scroll end
                 */
                objContainer.style.display = 'block';
            }
            else
            {
                this.hideSuggestions();
            }
	},
	successLoading: function(req)
	{
        var objContainer = this.createContainer();
		var xml = req.responseXML;
		
		var words = xml.getElementsByTagName('words');
		if  ( words && words[0] )
        { 
			setTimeout(function(words, objContainer){
				this.DrawContainer(words, objContainer);
			}.bind(this,words, objContainer), 1);
		}
		else
		{
			this.hideSuggestions();
		}
		
		this.AjaxRequest = null;
		Utils.removeLoadingEffect('suggestionsLoadingEffect');
	},
	
	/*
	* Hides Suggestion container
	*/
	hideSuggestions: function()
	{
		if ( $('suggestions')/* && this.isContainerOpened()*/ )
		{
			$('suggestions').setStyle({
				'display':'none'
			});
			this.lastRequest = '';
			this.resetSelectedIndex();
			
			var objContainerInner = $('suggestions').down('div.dropInner');
            
			if (objContainerInner)
			{
				objContainerInner.update('');
			}
			
            
			if ($(this.scrollUpId))
			{
				$(this.scrollUpId).remove();
			}
			
			if ($(this.scrollDownId))
            {
                $(this.scrollDownId).remove();
            }
			
			Utils.removeLoadingEffect('suggestionsLoadingEffect');
			
			this.hideTimerReset();
			
			this.AjaxRequest = null;
		}
	},

    isContainerOpened: function()
    {
        if ( $('suggestions') && $('suggestions').getStyle('display') != 'none' ) 
        {
            return true;
        }
        return false;
    },

	/*
	* Sets timeout
	*/
	hideTimerSet: function()
	{
		if (this.timer) clearTimeout(this.timer);
		this.timer = setTimeout(this.hideSuggestions.bind(this), this.hideTimeOut);
	},

	/*
	* Resets timeout
	*/
	hideTimerReset: function()
	{
		if (this.timer) clearTimeout(this.timer);
		if (this.showTimer) clearTimeout(this.showTimer);
	},

	/*
	* Creates suggestion container
	*/
	createContainer: function ()
	{
		if ( $('suggestions') )
		{
			this.containerPosition($('suggestions'));
			return $('suggestions');
		}
		return null;
	},

	/*
	* Sets focus and change selectedIndex
	* @param	{String}	action
	*/
	setSuggestFocus: function ( action )
	{
		if ( !this.isContainerOpened() ) 
		{
			return;
		}
		var suggestionsObj = $('suggestions').down('div.dropInner'); 
		if ( suggestionsObj )
		{
			this.hideTimerReset();
			var els = suggestionsObj.getElementsByTagName('A');
			if ( els )
			{
				for ( var i = 0; i < els.length; i++ )
					els[i].className = 'out';

				if ( action == 'down' )
					this.selectedIndex++;
				else
					this.selectedIndex--;

				switch( this.selectedIndex )
				{
					case -1:
					case -2:
						this.selectedIndex = els.length-1;
					break;

					case els.length:
					this.selectedIndex = 0;
					break;
				}

				els[this.selectedIndex].className = 'over';
				if ( suggestionsObj && suggestionsObj.style.display == '' )
				{
					if (els[this.selectedIndex])
					{
						els[this.selectedIndex].focus();
					}
				}
				return;
			}
		}
	},

	/*
	* This function provides keys handle
	* @param	{object MouseEvent}	evt
	*/
	handleArrowKeys: function ( evt )
	{
		var evt = (evt) ? evt : ((window.event) ? event : null);
	    if (evt) 
		{
	        switch (evt.keyCode) 
			{
				case Event.KEY_UP: //up 38
				{
					this.setSuggestFocus('up');
                    break;
				}

	            case Event.KEY_DOWN: //down 40
	            {
					this.setSuggestFocus('down');
                    break;
				}
	         }
	    }
	},

	/*
	* Sets suggestion container position
	* @param	{object HtmlElement}	container
	*/
	containerPosition: function ( container )
	{
		container.setStyle({
			'top': Utils.getTopPos(this.objField)+this.objField.getHeight()+'px',
			'left': (Utils.getLeftPos(this.objField)-10)+'px',
			'width': (this.objField.getWidth()+20)+'px'
		});
	}

}