jQuery.noConflict();

	// the jQuery background-position animation plugin
	
	/**
	 * @author Alexander Farkas
	 * v. 1.02
	 */
	jQuery.extend(jQuery.fx.step,{
		backgroundPosition: function(fx) {
			if (fx.state == 0 && typeof fx.end == 'string') {
				var start = jQuery.curCSS(fx.elem,'backgroundPosition');
				start = toArray(start);
				fx.start = [start[0],start[2]];
				var end = toArray(fx.end);
				fx.end = [end[0],end[2]];
				fx.unit = [end[1],end[3]];
			}
		
			var nowPosX = [];
			nowPosX[0] = ((fx.end[0] - fx.start[0]) * fx.pos) + fx.start[0] + fx.unit[0];
			nowPosX[1] = ((fx.end[1] - fx.start[1]) * fx.pos) + fx.start[1] + fx.unit[1];           
			fx.elem.style.backgroundPosition = nowPosX[0]+' '+nowPosX[1];
		
			function toArray(strg){
				strg = strg.replace(/left|top/g,'0px');
				strg = strg.replace(/right|bottom/g,'100%');
				strg = strg.replace(/(\d+)(\s|\)|$)/g,"$1px$2");
				var res = strg.match(/(\d+)(px|\%|em|pt)\s(\d+)(px|\%|em|pt)/);
				return [parseFloat(res[1]),res[2],parseFloat(res[3]),res[4]];
			}
		}
	});

	/* a generic random string generator, so we can give 
	   XML nodes a token if they don't already have one */
	   
	jQuery.randomString = function() {
		var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
		var string_length = 8;
		var randomstring = '';
		for(var i = 0; i < string_length; i++) {
			var rnum = Math.floor(Math.random() * chars.length);
			randomstring += chars.substring(rnum,rnum+1);
		} return randomstring;
	};

	/* carve out a namespace for the tour behaviors and
	   retrieve the content via an AJAX call */

	jQuery.fn.tour = function(options) {
		jQuery.fn.tour.settings = jQuery.extend({}, jQuery.fn.tour.defaults, options);
		return this.each(function(){
			jQuery(this).append('<div id="viewer"></div>');
			jQuery.fn.tour.viewer = jQuery('#viewer', jQuery(this));
			jQuery.get(jQuery.fn.tour.settings.structure, function($doc){
				jQuery('*', $doc).each(function(){
					if(!jQuery(this).attr('token')) jQuery(this).attr('token', jQuery.randomString());
				});
				jQuery.fn.tour.data = $doc;
				jQuery.fn.tour.render();
			});
		});
	};
	
	jQuery.fn.tour.defaults = {
		color: '#333333',
		structure: 'fairhaven.xml'
	};
	
	/* start rendering the markup for the viewer & menu
	   and store some commonly-used variables within the
	   jQuery.fn.tour namespace for easy access */
	
	jQuery.fn.tour.render = function() {
		jQuery.fn.tour.viewer.css('background-color', jQuery.fn.tour.settings.color);
		jQuery.fn.tour.viewer.before('<div id="tour-menu"></div>');
		// jQuery.fn.tour.viewer.before('<a href="#" id="tour-reset">Reset Tour</a>');
		jQuery.fn.tour.menu = jQuery('#tour-menu');
		jQuery.fn.tour.root = jQuery('place', jQuery.fn.tour.data).eq(0);
		
		// start building the tiers recursively
		jQuery.fn.tour.menuTier(jQuery.fn.tour.root);
	};
	
	/* 'activate' the viewer, meaning that the menu 
	   bar collapses down to a mini style and reveals
	   the viewing area beneath it */
	   
	jQuery.fn.tour.activate = function() {
		jQuery.fn.tour.menu.addClass('active');
		
		// hide the description blocks; we don't need them anymore
		jQuery('.description').fadeOut('fast');
		
		// find the last tier and make it look unset
		jQuery('li.tier:last-child').css({
			backgroundColor: '#888',
			backgroundImage: 'none'
		});
		
		// animate the height of the menu
		jQuery.fn.tour.menu.animate({
			height: '35px',
			top: 0
		}, 1800, 'easeOutExpo', function(){
			
		});
		
		jQuery('#tour-reset').click(function(e){
			e.preventDefault();
		});
	};
	
	/* build a level of the tour menu by passing
	   in a node and rendering its children */
	
	jQuery.fn.tour.menuTier = function($node) {
		var $menu = jQuery('<select onchange="jQuery.fn.tour.go(jQuery(this).parent())"></select>');
		
		// create a default option tag
		$menu.append('<option selected="selected" value="default">Choose One</option>');
		
		// create option for each child of this node...
		$node.children().each(function(){
			$kind = jQuery(this)[0].tagName;
			$attributes = jQuery(this)[0].attributes;
			$option = jQuery('<option value="'+jQuery(this).attr('token')+'">'+jQuery(this).attr('name')+'</option>');
			if($kind == 'pano') $option.append(" (VR)");
			$option.data('attrs', $attributes);
			$option.data('kind', $kind);
			$menu.append($option);
		});
		
		// assign tier to a class level
		$menu = jQuery('<li class="tier tier-'+$node.parents().size()+'"></li>').prepend($menu);
		
		// inject the description block for the tier
		$menu.append('<div class="description">'+$node.attr('description')+'</div>');
		
		// show the menu
		$menu.hide().fadeIn('slow');
		
		// append the menu
		jQuery.fn.tour.menu.append($menu);
		
		// watch for changes to the menu selection
		
		/* IE6 doesn't seem to like jQuery's .change() method... nor
		   does it seem to like .onchange (as this doesn't work either).
		   It looks to me like IE6 just doesn't bubble the Change
		   event up the DOM. I'm not sure how that applies to this
		   situation, though. */
		
/*
		$menu.change(function(){
			jQuery.fn.tour.go(jQuery(this));
		});
*/
/*
		
		$menu[0].onchange = function(e){
			jQuery.fn.tour.go(jQuery(e.srcElement));
		};
*/
	};
	
	jQuery.fn.nodeAttr = function($s) {
		if(this.data('attrs') && this.data('attrs').getNamedItem($s)) return this.data('attrs').getNamedItem($s).value;
	};
	
	jQuery.fn.tour.loadVr = function($node) {
		jQuery.fn.tour.viewer.empty();
		jQuery('<div class="tour-vr"></div>').appendTo(jQuery.fn.tour.viewer);
		jQuery('.tour-vr', jQuery.fn.tour.viewer).quicktime(null, { version: 7, update: false }, function(htmlOptions){
			$this = jQuery(this);
			
			htmlOptions.src = $node.nodeAttr('src');
			if($node.nodeAttr('height')) htmlOptions.height = $node.nodeAttr('height');
			if($node.nodeAttr('width')) htmlOptions.width = $node.nodeAttr('width');
			if($node.nodeAttr('fov')) htmlOptions.fov = $node.nodeAttr('fov');
			if($node.nodeAttr('pan')) htmlOptions.pan = $node.nodeAttr('pan');
			$this.before(jQuery.fn.quicktime.transform(htmlOptions));
		}).css({ width: '800px', height: '212px' });
		return;
	};
	
	jQuery.fn.tour.go = function($curselect){
		$curselect.nextAll().remove();
		$curselect.css({
			backgroundImage: 'url(./_media/tour/menu_arrow_semi-set.gif)'
		});
		
		// find the option that's been selected...
		jQuery('option:selected', $curselect).each(function(){
		
			// if the node type is not a grouping...
			if(jQuery(this).data('kind') != 'place') {
			
				// make it look set
				jQuery.fn.tour.menu.css('background-color', '#888');
			} else {
			
				// make it look un-set
				jQuery.fn.tour.menu.css('background-color', '#333');
			}
			
			// if the node selection is not the default option...
			if(jQuery(this).val() != 'default') {
				
				// how do you describe an animation in a comment?
				jQuery(this).parents('.tier').css({
					backgroundPosition: '400px 10%',
					backgroundColor: '#333'
				}).animate({
					backgroundPosition: '(right 50%)'
				}, 'fast', function(){
					jQuery(this).css({
						backgroundColor: '#888'
					});
				}).addClass('set');				
				
				// make it look set
				jQuery.fn.tour.menu.css({
					backgroundImage: 'url(./_media/tour/menu_head_set.gif)'
				});
				
				// make the previous look set
				$curselect.prevAll().css({
					backgroundImage: 'url(./_media/tour/menu_arrow_set.gif)'
				});
			} else {
			
				// make it look set
				jQuery(this).parents('.tier').css({
					backgroundColor: '#333',
					backgroundImage: 'none'
				}).removeClass('set');
				
				if(jQuery('li.tier').index(jQuery(this).parents('.tier')) == 0) {
				
					// make the menu look unset
					jQuery.fn.tour.menu.css({
						backgroundColor: '#333',
						backgroundImage: 'url(./_media/tour/menu_head.gif)'
					});
				} else {
					jQuery(this).parents('.tier').prev().css({
						backgroundImage: 'url(./_media/tour/menu_arrow_semi-set.gif)'
					});
					jQuery.fn.tour.menu.css({
						backgroundColor: '#333'
					});
				}
			}
			
			/* check the kind of the XML node and populate 
			   the viewer accordingly */
			  
			/* NOTE: directly accessing the key->value data inside of
			   a Attributes object cannot be done directly in IE6/7.
			   My guess is that they're not treated like an Array in IE
			   the way that an Object literal might be. So instead, use 
			   the Attribute object's .getNamedItem() method to retrieve 
			   a single element from the Attribute object set, and then
			   access its .value property. This works in Safari as well. */
			 
			switch(jQuery(this).data('kind')){
				case 'place':
					jQuery.fn.tour.menuTier(jQuery("place[name='"+jQuery(this).nodeAttr('name')+"']", jQuery.fn.tour.data));
				break;
				case 'image':
					jQuery.fn.tour.activate();
					$n = jQuery("image[token='"+jQuery(this).attr('value')+"']", jQuery.fn.tour.data);
					jQuery.fn.tour.viewer.empty().append('<img src="'+jQuery(this).nodeAttr('src')+'" alt="'+jQuery(this).nodeAttr('name')+'" />').hide().fadeIn('slow');
				break;
				case 'qtvr':
					jQuery.fn.tour.activate();
					jQuery.fn.tour.loadVr(jQuery(this));
				break;
				case 'pano':
					$vars = { 
						xml_file: './_media/tour/pano_settings.xml',
						panoName: './_media/tour/'+jQuery(this).nodeAttr('token')+'/'+jQuery(this).nodeAttr('token')
/*
						layer_1 : "./_media/tour/_plugins/autorotator.swf",
						layer_2 : "./_media/tour/_plugins/limits.swf",
						tilt: jQuery(this).nodeAttr('tilt'),
						tiltHome: jQuery(this).nodeAttr('tiltHome'),
						tilt_min: jQuery(this).nodeAttr('minTilt'),
						tilt_max: jQuery(this).nodeAttr('maxTilt'),
						pan: jQuery(this).nodeAttr('pan'),
						panHome: jQuery(this).nodeAttr('panHome'),
						pan_min: jQuery(this).nodeAttr('minPan'),
						pan_max: jQuery(this).nodeAttr('maxPan'),
						zoomHome: jQuery(this).nodeAttr('zoomHome'),
						zoom: jQuery(this).nodeAttr('zoom'),
						zoomMax: jQuery(this).nodeAttr('zoomMax'),
						zoomMin: jQuery(this).nodeAttr('zoomMin'),
						vfov: jQuery(this).nodeAttr('vfov'),
						hfov: jQuery(this).nodeAttr('hfov')
*/
					};
					jQuery.fn.tour.viewer.empty();
					jQuery.fn.tour.viewer.flash({
						flashvars: $vars,
						src: jQuery(this).nodeAttr('src'),
						width: jQuery(this).nodeAttr('width'),
						height: jQuery(this).nodeAttr('height')
					});
					jQuery.fn.tour.activate();
				break;
				default:
				break;
			}
		});
	}
	
	// make it so.
	jQuery(document).ready(function(){
		jQuery('#vtour').tour({
			structure: './_media/tour/tour.xml'
		});
	});

