var Suggest = new Class({ 
	
	Implements: Log,
	
	options: {
		listtype: 'ul',
		parent_id: 'suggest_element',
		parent_class: 'suggest',
		children_class: 'suggest_item'
	},
	
	initialize: function( element, url, options ){
		if( !element ){
			return;
		}
		this.enableLog().log('Initializing test');
		this.setOptions( options );
		this.position = { x:-1, y: -1 };
		this.lookupElement = $(element);
		this.displayElement = null;
		this.hrefs;
		this.selectedElement = -1;
		
		function handlekeydown( e ){
			if( ! e ) var e = window.event;
			if(e.code == 40 && this.isShowing) return false; 
		}
		
		//this.lookupElement.addEvent( 'blur', this.closeSuggest.bind(this) ) ;
		this.lookupElement.addEvent( 'keyup', this.suggest.bind(this) );
		this.lookupElement.addEvent( 'keydown',  handlekeydown );
		
		
		var pos = this.lookupElement.getPosition();
		var size = this.lookupElement.getSize();
		
		this.request = new Request.JSON({
			url: url,
			onComplete: this.response.bind(this)
		});
		this.request.setHeader('Cache-Control', 'no-cache');
		
		this.position.x = pos.x;
		this.position.y = pos.y + size.y;
		this.width = size.x;
	},
	
	calculatePosition: function(){
		var pos = this.lookupElement.getPosition();
		var size = this.lookupElement.getSize();
				
		this.position.x = pos.x;
		this.position.y = pos.y + size.y;
		this.width = size.x;
		
	},
	
	createParent: function(){
		this.displayElement = new Element( this.options.listtype, {'class': this.options.parent_class, 'id': this.options.parent_id } );
		this.displayElement.inject( $(document.body), 'top' );
	},
	
	suggest: function( e ){
		this.log("suggest");
		if( !e ) var e = window.event;
		
		var suchbegriff = this.lookupElement.value;
		if (suchbegriff.length == 0) {
			this.closeSuggest();
			return;
		} else {
			if( this.handleLookupKey( e ) ){
				return
			}
			var data = "&q="
				+ suchbegriff;
			if( sessionid ){
				data+= "&" + sessionid; 
			}		
			this.request.send({
				method: "get",
				data: data});
		}	
	},
	
	closeSuggest: function(){
		if( this.displayElement == null ){
			this.displayElement = $(this.id);
			if( this.displayElement == null ){
				return;
			}
		}
		setElementVisible(this.displayElement, false);
		if( MSVER < 7 ){
			ieHide( this.displayElement, false);
		}
		this.displayElement.innerHTML = "";
		this.isShowing = false;
		this.setBorderRadius("5px");
	},
	
	handleLookupKey: function( e ){
		if (!e) var e = window.event;
		var handled = false;
		switch( e.code ){
			case 9:
				handled = true;
				break;
			case 0:
			case 13: //enter
				handled = true;
				break;
			case 16:
			case 17:
			case 18:
			case 20:
			case 37:
			case 39:
				handled=true;
				break;
			case 27: //escape
				this.closeSuggest();
				handled = true;
				break;
			case 38: //arrow up
				this.select(e, true);
				handled = true;
				break;
			case 40: //arrow down
				this.select(e, false);
				handled = true;
				break;
		}
		if( handled ){
			consumeEvent(e);
		}
		return handled;
	},
	
	handleDisplayKey: function( e ){
		if (!e) var e = window.event;
		var handled = false;
		switch( e.code ){
			case 9:
				handled = true;
				break;
			case 13: //enter
				this.setValueFromEvent( e );
				handled = true;
				break;
			case 0:
			case 16:
			case 17:
			case 18:
			case 20:
			case 37:
			case 39:
				handled=true;
				break;
			case 27: //escape
				this.closeSuggest();
				handled = true;
				break;
			case 38: //arrow up
				this.select(e, true);
				handled = true;
				break;
			case 40: //arrow down
				this.select(e, false);
				handled = true;
				break;
		}
		if( handled ){
			consumeEvent(e);
		}
		return !handled;
	},
	
	select: function( e, backward ){
		if( backward ){
			if( this.selectedElement < 0 ){
				return;
			}
			else if( this.selectedElement == 0 ){
				this.lookupElement.focus();
				this.selectedElement = -1;
				return;
			}
			this.selectedElement--;
		}
		else{
			if( !this.hrefs || this.selectedElement >= this.hrefs.length - 1){
				this.lookupElement.focus();
				this.selectedElement = -1;
				return;
			}
			this.selectedElement++;
		}
		var a =this.hrefs[this.selectedElement];
		a.focus();
	},
	
	createGroup: function( group, g_index, g_array ){
		if( ! group.suggest.each ) return;
		this.dt = new Element('dt');
		this.dt.set( 'text', group['@attributes'].name );
		this.dt.inject(this.displayElement);
		group.suggest.each(this.createSuggest, this);
	},
	
	createSuggest: function( suggest, s_index, s_array ){
		var li;
		if( this.options.listtype == 'dl' ){
			li = new Element('dd');
		}else{
			li = new Element('li');
		}
		var a = this.createSuggestLink( suggest );
		a.addEvent('click', this.setValueFromEvent.bind(this));
		a.addEvent('keydown', this.handleDisplayKey.bind(this));
		a.addEvent('keypress', function(){return false;});
		a.inject(li);
		li.inject(this.displayElement);		
	},
	
	createSuggestLink: function( text, link){
		return new Element('a', {'text': text, 'class': this.options.children_class, 'href': link?link:'#' } );
	},
	
	response: function( response, responseText ) {
		this.log("response");
		if( this.displayElement == null ){
			this.createParent();
		}else{
			this.displayElement.empty();
		}
		
		if( responseText.length > 0 && response != null){
			this.openSuggest( response);
		}else{
			this.closeSuggest();
		}	
	},
	
	openSuggest: function( response ){
		
		this.log("openSuggest");
		
		this.calculatePosition();

		var selector = 'a.' + this.options.children_class;
		

		if( this.options.listtype == 'dl'){
			if( ! response.group.each ) return;
			response.group.each( this.createGroup, this );
		}else{
			if( ! response.suggest.each )
				this.createSuggest(response.suggest, 0, null);
			else
				response.suggest.each( this.createSuggest, this );
		}
		
		this.hrefs = this.displayElement.getElements(selector);
		this.selectedElement = 1;
		
		this.displayElement.setPosition(this.position );		
		this.displayElement.style.minWidth = this.width  + "px";


		this.selectedElement=-1;
		
		setElementVisible(this.displayElement, true );
		if( MSVER < 7){
			ieHide( this.displayElement, true);
		}
		this.isShowing = true;
		this.setBorderRadius("0");
	},
	
	setValue: function( value ){
		this.closeSuggest();
		if( this.lookupElement.type=="textarea"){
			this.lookupElement.value = value.replace( '[n]', '\n', 'g' ); 
		}else{
			this.lookupElement.value =  value;
		}
		this.lookupElement.focus();	
	},
	
	setValueFromEvent: function( e ){
		if( !e ) var e = window.event;
		var el;
		var t;
		if( e.target )
			el = e.target;
		else
			el = e.originalTarget;
				
		if( el.getParent().nodeName == 'DD'){
			var dt = el.getParent().getPrevious('dt');
			t = dt.get('text');
		}
			var c = getElementContent(el);
		if( t ){
			this.setValue( t + ": " + c ); 
		}else{
			this.setValue(c);
		}			
	},
	
	setBorderRadius: function ( radius ){
		var s = this.lookupElement.style;
		
		try{
			s.MozBorderRadiusBottomleft = radius;
			s.MozBorderRadiusBottomright = radius;
			return;
		}catch( e ){
		}
		try{
			s.BorderBottomLeftRadius = radius;
			s.BorderBottomRightRadius = radius;
			return;
		}catch( e ){
		}
		try{
			s.KhtmlBorderBottomLeftRadius = radius;
			s.KhtmlBorderBottomRightRadius = radius;
			return;
		}catch( e ){
		}
		try{
			s.WebkitBorderBottomLeftRadius = radius;
			s.WebkitBorderBottomRightRadius = radius;
			return;
		}catch( e ){
		}
	}
});

Suggest.implement(new Options);

