Element.addMethods({
	getValue: function(element) {
		if(document.all) {
			return $(element).innerText;
		} else {
			return $(element).textContent;
		}
	}
});

function Inspiration(){

	this.debug = false;
	this.pe = null;
	this.peInterval = 1; // interval (in seconds) to run the fetch
	this.monthSlider = null;
	this.wsBase = '/ws/inspiration.svc/getdestinations/';
	this.imagePath = window.location.hostname == 'audleytravel' ? 'http://audleywebapp/imageresizehandler/' : 'http://images1.audleytravel.com/';	
	this.qs = null;
	this.requestData = false;
	this.loadString = '<h2><img src="/images/home/inspiration/ajax-loader.gif" />Loading results...</h2>';
	this.data = [];

	this.init = function() {
		
		// add combo actions
		$$('#themeBox', '#categoryBox').each(function(el){
			el.observe('click', this.toggleDropdown.bind(this));
		}.bind(this));
		
		// add hovers to each combo option
		$$('.option').each(function(el){
			
			// add mouseover hover
			el.observe('mouseover', function(ev){
				el.addClassName('hover');
			});
			
			// add mouseout hover
			el.observe('mouseout', function(ev){
				el.removeClassName('hover');
			});
			
			// add click
			el.observe('click', this.selectOption.bind(this));
			
		}.bind(this));
		
		// add the clear form action
		$$('.clearForm a')[0].observe('click', this.clearForm.bind(this));
		
		// create the month slider
		this.monthSlider = new Control.Slider($('monthSlider').select('.handle'), $('monthSlider'), {
			range: $R(1,12),
			values: $R(1,12),
			sliderValue: [1,12],
			increment: 24,
			minimum: 1,
			maximum: 12,
			// restricted: true,
			onSlide: this.updateMonthSlider.bind(this),
			onChange: this.updateMonthSlider.bind(this)
		});
		
		this.updateFromHash();
		
		// create the PE
		this.pe = new PeriodicalExecuter(this.fetch.bind(this), this.peInterval);
		
	}
	
	this.updateFromHash = function() {
		hash = window.location.hash;
		hash = hash.replace('#', '');
		if(hash != '' && hash != null) {
			pairs = hash.split('|');
			pairs.each(function(pair){
				parts = pair.split('=');
				key = parts[0];
				value = parts[1];
				switch(key) {
					case 'theme':
					case 'category':
					case 'subcategory':
						value = value.replace('{', '');
						value = value.replace('}', '');
						//value = value.replace(/-/gi, '');
						li = $('id-' + value);
						if(li) {
							id = li.identify();
							this.selectOption(id);
						}
					break;
					case 'min':
						this.monthSlider.setValue(value, 0);
					break;
					case 'max':
						this.monthSlider.setValue(value, 1);
					default:
					break;
				};
			}.bind(this));
		}
	}
	
	this.toggleDropdown = function(ev) {
		box = (ev.element().hasClassName('box')) ? ev.element() : ev.element().up('.box');
		options = box.down('.options');
		if(options.visible()) {
			// hide the options
			options.hide()
		} else {
			// hide all other options and show the current option
			$$('.box .options').each(function(el){
				if(el.visible()) {
					el.hide();
				}
			})
			options.show();
		}
	}

	this.selectOption = function(ev) {
		if(typeof ev == 'object') {
			ev.stop();
			el = ev.element();
		} else {
			el = $(ev);
		}
		
		$$('.results')[0].update();
		
		option = (el.tagName == 'LI') ? el : el.up('li');
		
		box = option.up('.box');
		
		if(box.id == 'filter' && option.hasClassName('selected')) {
			option.removeClassName('selected');
		} else {
		
			// clear all other selected options
			box.select('.selected').each(function(el){
				el.removeClassName('selected');
			});
		
			option.addClassName('selected');
		
			if(box.hasClassName('dropdown')) {
				box.down('.options').hide();
				box.down('.value').update(option.down('.title').getValue());
			}
		
			switch(box.id) {
				case 'themeBox':
					// hide all the category menus
					$$('#categoryBox ul').each(function(menu){
						menu.hide();
					});
			
					// deselect all the categories
					$$('#categoryBox .selected').each(function(option){
						option.removeClassName('selected');
					});
					
					// deselect the filter
					$$('#filter .selected').each(function(el){
						el.removeClassName('selected');
					});
				
					// hide the filter
					$('filter').hide();
			
					// if the chosen item has an id (ie isn't a catch-all)
					if(box.down('.selected .id')) {
						// update the available category options
						index = option.previousSiblings().length
						$$('#categoryBox ul')[index].show();
					}
					// clear the value of the category box
					$$('#categoryBox .value')[0].update();
				break;
				case 'categoryBox':
					// update the available filter options
					index = option.previousSiblings().length;
					option.up('.options ul').previousSiblings().each(function(el, i){
						index = index + el.select('li .id').length;
					});
					$$('#filter .selected').each(function(el){
						el.removeClassName('selected');
					});
					$('filter').select('ul').map(Element.hide);
					if(this.category() != null) {
						$$('#filter ul')[index].show();
						$('filter').show();
					} else {
						$('filter').hide();
					}
				break;
				case 'filter':
				break;
			}
		}		
	
		this.updateForm();
		
	}

	this.toggleClearForm = function() {
		if(this.theme() == null) {
			$$('.clearForm')[0].hide();
		} else {
			$$('.clearForm')[0].show();
		}
	}
	
	this.updateForm = function() {
		this.toggleClearForm();
		newQS = this.getQS()
		if(newQS != this.qs) {
			if(this.debug) console.log('Query string: ', newQS);
			this.qs = newQS;
			this.requestData = true;
		}
	}
	
	this.fetch = function() {
		if(this.requestData && this.qs != '' && Ajax.activeRequestCount == 0) {
			url = this.wsBase + this.qs;
			if(this.debug) console.log('Webservice URL: ', url);

			// create the ajax request
			request = new Ajax.Request(url, {
				method: 'get',
				onCreate: function(transport) {
					$$('.results')[0].update(this.loadString);
				}.bind(this),
				onSuccess: function(transport) {
					this.transport = transport;
					
					results = transport.responseXML.documentElement.firstChild.childNodes;
					
					this.parseResponse(results);
					this.formatResponse();
					
				}.bind(this),
				onFailure: function(transport) {
					this.transport = transport;					
					$$('.results')[0].update('<h2>No results found</h2>');
				}.bind(this),
				onComplete: function(transport) {
					// if(this.debug) console.log('Request returned: ', transport.status, transport.statusText);
					this.requestData = false;
				}.bind(this)
			});

			this.requestData = false;

		}
	}

	this.parseResponse = function(results) {
		
		// clear the data global var
		this.data = [];
		
		// count the results
		var numResults = results.length
		$$('.results')[0].update('<h2>We recommend (' + numResults + ' results):</h2>');
		
		for(var i = 0; i < numResults; i++) {
			result = results[i];
			
			var countryName = (result.getElementsByTagName('Name')[0].firstChild != null) ? result.getElementsByTagName('Name')[0].firstChild.data : null;
			var countryIconicImage = (result.getElementsByTagName('IconicImage')[0].firstChild != null) ? result.getElementsByTagName('IconicImage')[0].firstChild.data : null;
			var countryUri = (result.getElementsByTagName('Uri')[result.getElementsByTagName('Uri').length-1].firstChild != null) ? result.getElementsByTagName('Uri')[result.getElementsByTagName('Uri').length-1].firstChild.data : null;
			var saturation = (result.getElementsByTagName('PlaceSaturation')[0].firstChild != null) ? parseInt(result.getElementsByTagName('PlaceSaturation')[0].firstChild.data) : null;
			var score = (result.getElementsByTagName('SuitabilityScore')[0].firstChild != null) ? parseInt(result.getElementsByTagName('SuitabilityScore')[0].firstChild.data) : null;
			
			var placeList = [];
			var places = result.getElementsByTagName('Places')[0].getElementsByTagName('Place');
			numPlaces = places.length;
			for(var x = 0; x < numPlaces; x++) {
				if(x < 3) {
					place = places[x];
					placeName = place.getElementsByTagName('Name')[0].firstChild.data;
					placeUri = place.getElementsByTagName('Uri')[0].firstChild.data;
					// if(this.debug) console.log('Country ', i, ' of ', numResults, ' Place ', x, ' of ', numPlaces, ': ', placeName);
					placeList.push({name: placeName, uri: placeUri});
				}
			}

			if(this.debug) console.log('Pushing', i+1, 'of', numResults, '- ', countryName, 'with', numPlaces, 'places');

			this.data.push({
				name: countryName,
				iconicImage: countryIconicImage,
				uri: countryUri,
				'places': placeList,
				'numPlaces': numPlaces,
				'saturation': saturation,
				'score': score
			});
			
		}
	}

	this.formatResponse = function() {

		if(this.debug) console.log('Showing results...');
		
		var pane = $$('.results')[0];
		pane.update('');
		
		switch(this.data.length) {
			case 0:
				pane.update('<h2>No results</h2>');
			break;
			case 1:
				pane.update('<h2>We recommend (one result):</h2>');
			break;
			default:
				pane.update('<h2>We recommend (' + this.data.length + ' results):</h2>');
			break;
		}
		
		container = new Element('div', {'class': 'resultsContainer'});
		
		this.data.each(function(country){
			
			var result = new Element('div', {'class': 'result'});
			
			if(country.iconicImage != null) {
				result.insert(
					new Element('a', {
						'class': 'iconic',
						'href': country.uri,
						'title': 'Read more'
					}).insert(
						new Element('img', {
							'class': 'iconic',
							'src': this.imagePath + '?w=140&h=100&q=80&id=' + country.iconicImage
						})
					)
				);
			} else {
				result.insert(
					new Element('a', {
						'class': 'iconic',
						'href': country.uri,
						'title': 'Read more'
					}).insert(
						new Element('div', {
							'class': 'iconic fauxImage'
						})
					)
				);
			}
			result.insert(
				new Element('h3').insert(
					new Element('a', {
						href: country.uri,
						title: 'Read more'
					}).update(country.name)
				)
			);
			
			if(country.places.length > 0) {
				result.insert(new Element('p').update('Places to consider'));
			
				placeList = new Element('ul');
			
				country.places.each(function(place, i){
					if(i < 3) {
						placeList.insert(
							new Element('li').insert(
								new Element('a', {
									href: place.uri,
									title: 'Read more about ' + place.name
								}).update('<img src="/images/icons/arrows/play.png" alt="Place" />' + place.name)
							)
						);
					}
				}.bind(this));
			
				result.insert(placeList);
				
				if(country.numPlaces > 3) {
					switch(country.numPlaces) {
						case 0:
						case 1:
						case 2:
						case 3:
							// do nothing
						break;
						case 4:
							result.insert(new Element('p').update(' and one other place'));
						break;
						case 5:
							result.insert(new Element('p').update(' and two other places'));
						break;
						case 6:
							result.insert(new Element('p').update(' and three other places'));
						break;
						case 7:
							result.insert(new Element('p').update(' and four other places'));
						break;
						case 8:
							result.insert(new Element('p').update(' and five other places'));
						break;
						case 9:
							result.insert(new Element('p').update(' and six other places'));
						break;
						default:
							result.insert(new Element('p').update(' and ' + (country.numPlaces - 3) + ' other places'));
						break;
					}
				}
			}
			
			container.insert(result);
		}.bind(this));
		
		pane.insert(container);
			
	}
	
	this.clearForm = function(ev) {
		ev.stop();
		$$('.box').each(function(box){
			box.select('.selected').each(function(el){
				el.removeClassName('selected');
			})
			if(box.down('.value')) {
				box.down('.value').update();
			}
			if(box.select('ul').length > 1) {
				box.select('ul').map(Element.hide);
			}
		});
		$('filter').hide();
		this.monthSlider.setValue(1, 0);
		this.monthSlider.setValue(12, 1);
		$$('.results')[0].update();
		this.updateForm();
	}

	this.updateMonthSlider = function(values) {
		values = values.map(Math.round).map(Math.round).sortBy(function(i){ return parseInt(i) });
//		rounded = values.map(Math.round);
//		rounded = rounded.sortBy(function(i){ return parseInt(i) });
		var monthStr = "<b>3. </b>I'd like to travel between ";
		if(values[0] == 1 && values[1] == 12) {
			monthStr = "<b>3. </b>I'd like to travel any time of year";
		} else if (values[0] == values[1]) {
			monthStr = "<b>3. </b>I'd like to travel in " + this.numberToMonth(values[0]);
		} else {
			monthStr =  monthStr + values.map(this.numberToMonth).join(' and ');
		}
		$('monthSlider').up('.box').down('.title').update(monthStr);

		this.updateForm();
	}

	this.numberToMonth = function(num) {
		switch(num) {
			case 1:
				return 'January';
			break;
			case 2:
				return 'February';
			break;
			case 3:
				return 'March';
			break;
			case 4:
				return 'April';
			break;
			case 5:
				return 'May';
			break;
			case 6:
				return 'June';
			break;
			case 7:
				return 'July';
			break;
			case 8:
				return 'August';
			break;
			case 9:
				return 'September';
			break;
			case 10:
				return 'October';
			break;
			case 11:
				return 'November';
			break;
			case 12:
				return 'December';
			break;
			default:
				return num;
			break;
		}
	}

	this.getQS = function() {

/*
		var qs = new Hash();
		
		if(this.theme() != null) {
			qs.set('theme', this.theme());
		}
		if(this.category() != null) {
			qs.set('category', this.category());
		}
		if(this.filter() != null) {
			qs.set('subcategory', this.filter());
		}
		months = this.months();
		if(months[0] != 1 || months[1] != 12) {
			qs.set('min', months[0]);
			qs.set('max', months[1]);
		}
*/

		var qs = '';
		if(this.theme() != null) {
			qs = qs + 'theme=' + this.theme();
			qs = qs + '|';
		}
		if(this.category() != null) {
			qs = qs + 'category=' + this.category();
			qs = qs + '|';
		}
		if(this.filter() != null) {
			qs = qs + 'subcategory=' + this.filter();
			qs = qs + '|';
		}
		months = this.months();
		if(months[0] != 1 || months[1] != 12) {
			qs = qs + 'min=' + months[0] + '|max=' + months[1];
		}

		hash = qs;
		window.location.hash = hash;

		if(qs.substring(0, 5) == 'theme') {
			qs = qs.substring(qs.indexOf('|') + 1);
		}

		return qs;

	}
	
	this.getID = function(el) {
		if(el.down('.selected .id')) {
			return el.down('.selected .id').getValue();
		} else {
			return null;
		}
	}

	this.theme = function() {
		return this.getID($('themeBox'));
	}

	this.category = function() {
		return this.getID($('categoryBox'));
	}

	this.filter = function() {
		return this.getID($('filter'));
	}

	this.months = function() {
		return this.monthSlider.values.sortBy(function(i){ return parseInt(i) });
	}
	
	this.init();
	
}

document.observe('dom:loaded', function(ev) {
    i = new Inspiration();    
});
