/*
 * Copyright (c) 2008 WeGotTickets
 * 
 * @Author Clive Calmeyer
 * @Revision $Id$
 * @Package www
 * 
 */


DataProvider = {
	search: function( q, callback ) {
		XHR.post( '/ajaxsearch', { wgtq: q }, callback );
	}
};

function WGTSuggest( inputElementId, suggestObject, dataProvider, options ) {
	var wgts = this;

	this.ip = $( inputElementId );
	this.ip.focus();
	this.sgst = suggestObject;
	this.dp = dataProvider;
	this.lastQuery = '';
	this.waiting = false;    //waiting in case there's more input
	
	this.active = this.ip;
	
	// set options
	options = options || {};
	this.minChars	 = options.minChars || 3;
	this.delay 	     = options.delay || 500;

	var sgst = this.sgst;
	addEvent( this.ip, 'keydown', function( e ) {
		if( e.keyCode == 9 || e.keyCode == 13 ) {
			e.preventDefault();
		}
	});
	addEvent( this.ip, 'keyup', function( e ) {
		e.preventDefault();
		switch( e.keyCode ) {
			case 9: //tab
				e.preventDefault();
				break;
			case 13: //enter
				wgts.submit();
				break;
			case 37: //right
			case 39: //left
				//ignore
				break;
			case 38: //up
				wgts.select( -1 );
				break;
			case 40: //down
				wgts.select( 1 );
				break;
			case 27: //esc
				wgts.select( 0 );
				break;
			default:
				wgts.search( this.value );
		}
	});
	
	addEvent( this.ip, 'focus', function( e ) {
		wgts.sgst.show();
		wgts.select(0);
	});
	
	addEvent( this.ip, 'blur', function( e ) {
		wgts.sgst.hide();
		wgts.unSelect();
	});
};

WGTSuggest.prototype.select = function( inc ) {
	var el = this.sgst.select( inc );
	if( el ) {
		this.active = el;
		$removeClass( 'active', this.ip );
	} else {
		this.active = this.ip;
		$addClass( 'active', this.ip );
	}
};

WGTSuggest.prototype.unSelect = function() {
	this.active = this.ip;
	$removeClass( 'active', this.ip );
};

WGTSuggest.prototype.submit = function( clickedItemId ) {
// clickedItemId is here temporarily in order to gather search success stats
	var action       = clickedItemId ? 'suggestion click' : 'suggestion enter';
	var event        = clickedItemId || this.active.id;
	var partialQuery = this.lastQuery;
	var query        = this.ip.value;

	if( this.active == this.ip && !clickedItemId ) {
		var form = this.ip.form;
		XHR.post(
            '/searchstats',
            {
                action: 'form submit enter',
                query:  query,
                partialQuery: partialQuery,
                userAgent: navigator.userAgent
            },
            function(){ form.submit() }
        );
	} else {
		XHR.post(
			'/searchstats',
			{
				action:       action,
				event:        '\/'+event,
				query:        query,
				partialQuery: partialQuery,
                userAgent: navigator.userAgent
			},
			function(){ window.location = '\/'+event; }
		);
	}
};

WGTSuggest.prototype.search = function( query ) {
	var wgts = this;
	var sgst = this.sgst;
	
	if( this.waiting ) {
		clearTimeout( this.waiting );
	}

	if( query.length < this.minChars ) {
		sgst.reset();
		return;
	}
	
	if( query.normalise() == this.lastQuery ) {
		return;
	}
	this.lastQuery = query.normalise();
	
	this.waiting = setTimeout( function() {
		sgst.wait();
		wgts.dp.search( query, function( result ) {
			if( !result ) {
				wgts.unSelect();
				sgst.reset();
				return;
			}
			wgts.createSelection( result[0] );
			result = result.slice(1)
			sgst.display( result );
			if( parseInt( result[1], 10 ) ) {
				wgts.select( 0 );
			} else {
				wgts.unSelect();
			}
		});
	}, this.delay ); 
};

//selects a portion of the input string
WGTSuggest.prototype.createSelection = function( suggestion ){
	// get a reference to the input element
	if( !suggestion ) return;
	var field = this.ip;
	var val = field.value;
	var start = val.length;
	
	var val = val.replace( /\w*$/, suggestion );
	var end = val.length;
	field.value = val;
	if( field.createTextRange ){
		var selRange = field.createTextRange();
		selRange.collapse(true);
		selRange.moveStart("character", start);
		selRange.moveEnd("character", end);
		selRange.select();
	} else if( field.setSelectionRange ){
		field.setSelectionRange(start, end);
	} else {
		if( field.selectionStart ){
			field.selectionStart = start;
			field.selectionEnd = end;
		}
	}
	field.focus();
};

function WGTSuggestionBox( elIds ) {
	this.el = $(elIds.container);
	this.throbber = $(elIds.throbber);
	this.payload = $(elIds.payload);
	this.mask = $(elIds.mask);

	this.list = [null];
	this.pointer = 0;
	this.payload.innerHTML = '';
	
// set up proxy events
// we are temporarily gathering search success stats so we have to do more work
// WGTS is the main object temporarily stored in a global variable (yuck)
//	proxy( 'div.sa_resultdiv', 'mousedown', function( e ) { window.location = '/'+this.id; }, this.el );
	proxy( 'div.sa_resultdiv', 'mousedown', function( e ) { WGTS.submit( this.id ); }, this.el );
	proxy( 'div.sa_resultdiv', 'mouseover', function( e ) { $addClass( 'hover', this ); }, this.el );
	proxy( 'div.sa_resultdiv', 'mouseout',  function( e ) { $removeClass( 'hover', this ); }, this.el );
	proxy( 'div.sa_event_info', 'mousedown',  function( e ) { WGTS.unSelect(); WGTS.submit(); }, this.el );

// this bit hides the highlighted option while mouse action is happening
// is a bit troublesome tho
//	addEvent( this.el, 'mouseover', function( e ) {
//		this.prev = $$('active')[0];
//		console.log( this.prev );
//		$removeClass( 'active', this.prev );
//	});
//	addEvent( this.el, 'mouseout', function( e ) {
//		$addClass( 'active', this.prev );
//		this.prev = null;
//	});
	
	this.hide = function() {
		this.el.style.display = 'none';
	}
	
	this.show = function() {
		if( this.payload.innerHTML == '' ) {
			return;
		}
		this.el.style.display = 'block';
		this.mask.style.height = this.payload.offsetHeight+"px";
	}
	
	this.reset = function() {
		this.payload.innerHTML = '';
		this.list.length = 1;
		this.pointer = 0;
	}
	
	this.select = function( inc ) {
		var pointer = this.pointer;
		if( this.list[pointer] ) {
			$removeClass( 'active', this.list[pointer] );
		}
		if( inc === 0 ) {
			pointer = 0
		} else {
			pointer += inc;
		}
		if( pointer >= this.list.length ) pointer = 0;
		if( pointer < 0 ) pointer = this.list.length-1;
		this.pointer = pointer;
		if( this.list[pointer] ) {
			$addClass( 'active', this.list[pointer] );
		}
		return this.list[pointer];
	}
	
	this.wait = function() {
		this.reset();
		$append( $create('blockquote', 'searching...' ), this.payload );
		this.show();
	}
	
	this.display = function( result ) {
		this.reset();
		var resultCount = parseInt( result[1], 10 );
		var data = result[0];
		$append(
				$create(
						'div',
						'<img src="\/images\/fullsearch_3.png">',
						{ 'class' : 'sa_event_info' }
				),
				this.payload
		);
		if( resultCount == 0 ) {
			$append(
				$create(
					'div',
					'<p>Sorry, we don\'t have any quick suggestions for your query. Please check your spelling '+
					'or click the search button to perform a more thorough search</p>',
					{ 'class' : 'sa_event_info' }
				),
				this.payload
			);
		}
		for( var i = 0; i < data.length; i++ ) {
			var item = $create(
					'div',
					'<span class="sa_event_name">'+data[i].name+'</span><br>'+
					'<span class="sa_event_venue">'+data[i].venue+'</span><br>'+
					'<span class="sa_event_date">'+data[i].date+'</span>',
					{ id: data[i].id, 'class': 'sa_resultdiv' }
			);
			this.list.push(item);
			$append( item, this.payload );
			
		}
		this.show();
	}
	
	this.messages = {
		'none': 'No suggestions',
		'few': ''
	}
	
};

String.prototype.normalise = function() {
	str = this.toLowerCase();
	// squash multiple spaces and trim (the fastest way )
	str = str.replace( /\s\s+/g, ' ' )
	         .replace( /^\s/, '' )
	         .replace( /\s$/, '' );
	return str;
};
