// tobicon class
var tobicon = new Class({
	// constructor
	initialize: function( input, options ) {
		// set the input box
		this.input = $(input);
		// the options
		this.options = new Hash({
			id: 'tobicon',
			style: 'magnify'
		});
		// add the options
		$extend(this.options,options);
		// add the div
		this.draw();
	},
	// This method will change the type of icon
	change: function( newclass, el ) {
		// set the class name
		this.icon.removeClass( this.options.style ).addClass( newclass );
		// for the close type we need to add the click event
		if( newclass == 'close' && $(el) ) {
			this.icon.addEvent( 'click', function(e) {
				// hide it
				el.setStyle( 'display', 'none' );
				// change the icon
				this.removeClass( 'close' ).addClass( 'magnify' );
			});
		} else {
			// otherwise we need remove the click event
			this.icon.removeEvent( 'click' );
		}
		// the style
		this.options.style = newclass;
	},
	// gets the current icon
	current: function(e) {
		return this.options.style;
	},
	// This method actually draws the div and adds it to the DOM.
	draw: function(e) {
		// add the element
		this.icon = new Element('div', {
			'id': this.options.id,
			'class': this.options.style,
			'styles': {
				'display': 'block',
				'position': 'absolute',
				'top': ( this.input.getCoordinates().top + ( Browser.Engine.trident4 ? 0 : 4 ) ),
				'left': ( this.input.getCoordinates().left + this.input.getCoordinates().width - 15 )
			}
		}).inject( document.body );
	}
});

var tobsearch = new Class({
	// constructor
	initialize: function( input, hidden, options ) {
		this.pathparts = escape(window.location.pathname).split(unescape("%2F"));
		this.baseurl = window.location.protocol + unescape("%2F%2F") + window.location.hostname;
		// check to see if we are on reverse proxy
		if( window.location.href.replace('http://','').replace('https://','').substr( 0, 12 ) == 'www.bbb.org/' ) {
			this.baseurl = this.baseurl + unescape("%2F") + this.pathparts[1];
		}
		// set the input box
		this.input = $(input);
		// set the icon
		this.icon = new tobicon( this.input );
		// set the hidden field
		this.hidden = $(hidden);
		// whether a post was sent
		this.sent = false;
		// the options
		this.options = new Hash({
			start: '[top25]',
			id: 'toblist',
			searchurl: '%2F' + this.pathparts[1] + '%2Fext%2Ftob.html',
			noactionkeys: [ 'enter', 'right', 'left', 'up', 'down', 'esc', 'shift' ],
			replacement: '<span class="highlight">$1</span>',
			endings: [ 'er', 'ers', 'ing', 'ings', 'es', 's', 'e' ],
			goto: this.baseurl + unescape('%2Faccredited-business-directory%2F'),
			searchbutton: '',
			additionalfields: new Hash(), // added fields to submit with the search
			submitform: '',
			onSelect: function( tob ) { return; }
		});
		// store the previous search string so we don't do a duplicate search
		this.searchstr = '';
		// add the options
		$extend(this.options,options);
		// add the div to the dom
		this.draw();
		// add the focus/keyup event to the search box
		var obj = this;
		this.input.addEvents({
			'focus': this.focus.bind(this),
			'blur': this.blur.bind(this),
			'keyup': function(e) {
				if( !obj.options.noactionkeys.contains( e.key ) )
					this.fireEvent( 'execute', this.value, 150 );	
			},
			'execute': this.search.bind(this)
		}).addEvent((Browser.Engine.trident || Browser.Engine.webkit) ? 'keydown' : 'keypress', this.keys.bind(this));
		// get the initial list
		this.search( this.options.start );
	},
	// submit the form is one is attached to the class
	formsubmit: function(e) {
		// make sure we have a form and it exists
		if( this.options.submitform.length > 0 ) {
			this.options.submitform.submit();
		}
	},
	// watch the keystrokes
	keys: function(e) {
		// do different things
		switch( e.key ) {
			case "up": this.choosePrevious(); break;
			case "down": this.chooseNext(); break;
			case "esc": this.input.blur(); this.icon.icon.fireEvent( 'click' ); break;
			case "enter": 
				new Event(e).stop();
				this.input.blur();
				this.choice.fireEvent('click');
				return;
			break;
		}
	},
	// focus event
	focus: function(e) {
		// set the icon
		this.icon.change( 'close', $( this.options.id ) );
		// show the list
		this.showList();
		// adjust the width/height for the size
		this.adjust();
	},
	// blur event for the input
	blur: function(e) {
		// fire the close button
		//this.icon.icon.fireEvent('click');	
	},
	// show the list
	showList: function(e) {
		// show the list
		$( this.options.id ).setStyle( 'display', 'block' );
		this.icon.change( 'close', $( this.options.id ) );
		//this.label.label.setStyle( 'top', this.list.getCoordinates().top + this.list.getCoordinates().height );			
	},
	// add the div and search prompt to the dom
	draw: function(e) {
		// add the element
		this.list = new Element('div', {
			'id': this.options.id,
			'styles': {
				'display': 'none',
				'position': 'absolute',
				'top': ( this.input.getCoordinates().top + this.input.getCoordinates().height ),
				'left': this.input.getCoordinates().left,
				'width': ( this.input.getCoordinates().width - 4 )
			}
		}).inject( document.body );
	},
	// perform a search
	search: function( query ) {
		if( ( query.length > 0 && this.input.value.length > 0 && query != this.searchstr ) || query == this.options.start ) {
			// make sure we haven't continued to type
			if( !this.sent && ( query == $(this.input).value || query == this.options.start ) ) {
    			// set the sent flag
    			this.sent = true;
				// store a reference to the list
				var obj = this;
				// set the search str
				this.searchstr = query;
				this.icon.change( 'busy' );
				// send the request
				new Request.HTML({
					url: unescape( this.options.searchurl ),
					onComplete: function() {
						// set the sent flag
						obj.sent = false;
						// set the results
						obj.list.set( 'html', this.response.html );
						// highlight the matching parts of the string
						if( query != obj.options.start ) obj.highlight( query );
						// highlight rows and adjust width
						obj.mouseover();
						obj.adjust();
						obj.chooseFirst( 'y' );
						obj.icon.change( 'magnify' );
						if( query != obj.options.start ) obj.showList();
					},
					data: $merge({'q': query,'where':'equote'},this.options.additionalfields)
				}).post();
			}
		}
	},
	// get the common endings to certain words
	commonendings: function( str ) {
		// set the common endings
		var endings = this.options.endings;
		// the string contianing each new word
		var output = '';
		// go through each keyword
		str.split(" ").each( function(word) {
			// save the original
			var original = word;
			// get rid of the ending
			endings.each( function(ending) {
				if( word.substr( -(ending.length ) ) == ending ) {
					word = word.substring( 0, word.length-ending.length );
				}
			});
			// add each ending onto the word
			endings.each( function(ending) {
				output += word + ending + ' ';
			});
			// make sure we add the original word as well
			output += original + ' ';
		});
		// return the output string and trim off the last space
		return output.replace( / $/g, '' );
	},
	// hiehglight parts of the string that match the query
	highlight: function( str ) {
		// get the common endings
		str = this.commonendings( str ).replace( new RegExp( " ","g" ),"|" );
		// whether it should be global or not
		var global = ( this.searchstr.length < 3 ? false : true );
		// what to replace the matched strings with
		var replacement = this.options.replacement;
		// go through each element and mark the matched strings/substrings
		$$( 'div#' + this.options.id + ' ul li' ).each( function(item, i ) {
			// we need to get the keywords separated by pipes for the regular expression
			var exp = new RegExp( '(' + ( global ? '' : '^' ) + str + ')', ( global ? "ig": "i" ) );
			// set the html to this new one
			item.set( 'html', item.get('text').replace( exp, replacement ) );
		});
	},
	// get the next item
	chooseNext: function() {
		// make sure there is a next one
		if( $( this.choice.getNext() ) )
			this.choose( this.choice.getNext(), 'y' );
		else
			this.chooseFirst();
	},
	// get the previous item
	choosePrevious: function() {
		// make sure there is a previous one
		if( $( this.choice.getPrevious() ) )
			this.choose( this.choice.getPrevious(), 'y' );
		else
			this.chooseLast();
	},
	// choose the first one
	chooseFirst: function( start ) {
		var obj = this;
		$$( 'div#' + this.options.id + ' ul' ).each( function(list ) {
			obj.choose( list.getFirst(), ( start == 'y' ? '' : 'y' ) );
		});
	},
	// choose the last one
	chooseLast: function() {
		this.choose( $$( 'div#' + this.options.id + ' ul li' ).getLast(), 'y' );
	},
	// this actually chooses an item
	choose: function( el, keyboard ) {
		// make sure it's valid element
		if( $(el) ) {
			// if we had a previous choice
			if( $( this.choice ) ) {
				this.choice.removeClass( 'chosen' );
			}
			// set the choice
			this.choice = $( el );
			// show that is has been chosen
			$( el ).addClass( 'chosen' );
			//alert( this.choice.innerHTML );
			// scroll to that choice
			if( keyboard == 'y' ) {
				//new Fx.Scroll(this.list).toElement(el);
				var coords = this.choice.getCoordinates(this.list);
				var margin = coords.height;
				var	top = this.list.scrollTop;
				var height = this.list.offsetHeight;
				var bottom = top + height;
				
			if( coords.top - margin < top && top )
				this.list.scrollTop = Math.max(coords.top - margin, 0);
			else if( coords.bottom + margin > bottom )
				this.list.scrollTop = Math.min(coords.bottom - height + margin, bottom);
			}
			// set the label
			//if( this.input.value.length > 0 )
				//this.label.set( this.choice.innerHTML.replace( /&amp;/gi, "&" ).replace(/(<([^>]+)>)/ig,"") );
		}
	},
	// make the width/height the right size if there is a scroll bar or not
	adjust: function(e) {
		//alert( this.list.getScrollSize().y );
		// set the width
		this.list.setStyle( 'width', ( this.input.getCoordinates().width + ( this.list.getScrollSize().y > 206 ? 15 : -4 ) ) );
		// set the height
		if( $$( 'div#' + this.options.id + ' ul li' ).length > 9 ) this.list.setStyle( 'height', 206 );
		else this.list.setStyle( 'height', 'auto' );
	},
	// the clicking event for each item
	click: function(e) {
		// set the hidden field
		this.hidden.value = this.choice.id;
		// populate the field
		this.input.value = this.choice.innerHTML.replace( /&amp;/gi, "&" ).replace(/(<([^>]+)>)/ig,"");
//		this.label.set( this.choice.innerHTML.replace( /&amp;/gi, "&" ).replace(/(<([^>]+)>)/ig,"") );
		// close the field
		this.icon.icon.fireEvent('click');
		if( $( this.options.searchbutton ) ) {
			$( this.options.searchbutton ).value = 'Please wait, Loading ...';
			$( this.options.searchbutton ).disabled = true;
		}
		// get a list of businesses
		this.options.onSelect( this.choice.id );
	},
	// add the list mouseover effects
	mouseover: function(e) {
		// add the mouse over effects
		var obj = this;
		$$( 'div#' + this.options.id + ' ul li' ).addEvents({
			'mouseenter': function() { obj.choose( this ); },
			'click': this.click.bind(this)
			//'mouseleave': function() { this.removeClass( 'hover' ); }
		}).setStyle( 'cursor', 'pointer' ).setStyle( 'padding-top', ( Browser.Engine.trident ? 0 : 5 ) );
	}
});
