(function($, w){
//============================================================
// site variables
	
var s = {
	
	// cache of the main site elements
	elements: {
		headerGraphic: null
		}
	
	};

//============================================================
// rotating image gallery

s.rotatingImageGallery = function(){
	
	// do we have any options?
	if (!w.imageRotatorGraphics){
		return false;
		}
	
	// get options
	var options = $.extend({}, s.rotatingImageGallery.defaultOptions, (w.imageRotatorOptions ? w.imageRotatorOptions : {}));
	
	// get graphics
	var graphics = w.imageRotatorGraphics;
	
	// load status
	var loadStatus = [];
	
	// current graphic
	var currentGraphic = 0;
	
	// backup the header graphic HTML
	var fallbackBackup = s.elements.headerGraphic.html();
	
	// get the loading spinner
	var loadingSpinner = $('<span class="loading-spinner"></span>').css({opacity: 0.8});
	
	// get the progress indicator
	var progressIndicator = $('<span class="progress-indicator"></span>');
	
	// clear the header graphic
	s.elements.headerGraphic
		.html('')
		.css({backgroundColor: options.backgroundColor})
		.append(loadingSpinner)
		.append(progressIndicator);
	
	// loop graphics and turn into proper graphic objects
	$.each(graphics, function(i){
		
		// create object
		graphics[i] = {
			aHref: graphics[i][0],
			imgSrc: graphics[i][1],
			aTarget: (graphics[i][2] ? graphics[i][2] : '_blank'),
			a: null,
			img: null,
			indicator: null,
			duration: (graphics[i][3] ? graphics[i][3] : options.duration)
			};
		
		// add load status
		loadStatus[i] = false;
		
		// create the indicator
		graphics[i].indicator = $('<span/>')
			.appendTo(progressIndicator);
		
		// create the image and bind load event
		graphics[i].img = $(['<img src="', graphics[i].imgSrc, '" alt=""/>'].join(''))
			.bind('load', {i: i}, function(event){
				
				// set loaded flag
				loadStatus[event.data.i] = true;
				
				})
			.bind('error abort', {i: i}, function(event){
				
				// stop the rotator
				//s.elements.headerGraphic.html(fallbackBackup).removeClass('rotator-loading');
				
				});
		
		// create the link and append the image to it
		graphics[i].a = $(['<a href="', graphics[i].aHref, '" target="', graphics[i].aTarget, '"></a>'].join(''))
			.append(graphics[i].img);
		
		// add the element to the header and hide
		graphics[i].a
			.appendTo(s.elements.headerGraphic)
			.css({display:'none'});
		
		});
	
	// resize the loading spinner
	loadingSpinner.width(progressIndicator.width()-1);
	
	// switchGraphic function
	var switchGraphic = function(i, firstload){
		
		// make sure the image is loaded
		if (!loadStatus[i]){
			
			// fade in the loading spinner
			if (loadingSpinner.css('opacity')<0.8){
				loadingSpinner.css({display:'block', opacity: 0}).animate({opacity: 0.8}, 200);
				}
			
			// delay the next image
			graphics[currentGraphic].a
				.animate({delay:1}, 200, function(){
					switchGraphic(i, firstload);
					});
			return;
			
			}
		else{
			
			// fade out the loading spinner
			loadingSpinner.animate({opacity: 0}, 200, function(){$(this).css({display:'none'});});
			
			}
				
		// fade out the old graphic
		if (!firstload){
			graphics[currentGraphic].a
				.animate({opacity: 0}, options.fadeDuration, function(){
					$(this).css({display:'none'});
					});
			}
		
		// set current graphic
		currentGraphic = i;
		
		// manage active states
		graphics[i].indicator.animate({delay:1}, options.fadeDuration/2, function(){
			// remove the active state from all indicators
			progressIndicator.find('span').removeClass('active');
			// add an active state to the new indicator
			$(this).addClass('active');
			});
		
		// fade in the new graphic
		graphics[i].a
			.css({display:'block', opacity: 0})
			.fadeTo(options.fadeDuration, 1, function(){
				
				$(this).animate({delay:1}, graphics[i].duration, function(){
					
					// next graphic
					var nextGraphic = 0;
					
					// work out what the next graphic will be
					if (i==graphics.length-1){
						nextGraphic = 0;
						}
					else{
						nextGraphic = i+1;
						}
					
					// switch the graphic
					switchGraphic(nextGraphic);
					
					});
				
				});
		
		};
	
	// display current graphic
	switchGraphic(currentGraphic, true);
	
	};

// default options
s.rotatingImageGallery.defaultOptions = {
	fadeDuration: 1500,
	duration: 3000,
	backgroundColor: '#eee'
	};

// add a custom parser
$.tablesorter.addParser({
	
	// set a unique id
	id: 'dayofweek',
	
	// no auto-detection please
	is: function(value) { return false; },
	
	// formatter function
	format: function(value) {
		value = value
			.toLowerCase()
			.replace(/monday/, 1)
			.replace(/tuesday/, 2)
			.replace(/wednesday/, 3)
			.replace(/thursday/, 4)
			.replace(/friday/, 5)
			.replace(/saturday/, 6)
			.replace(/sunday/, 7);
		return value;
	},
	
	// numeric type
	type: 'numeric'
	
});


//============================================================
//document load

$(function(){
	
	// add the script class to the body
	$('body').removeClass('noscript').addClass('script');
	
	// cache main site elements
	s.elements.headerGraphic = $('#header-graphic');
	
	// add rotating image gallery
	s.rotatingImageGallery();
	
	$('#timetable')
		.tablesorter({headers: {2:{sorter: 'dayofweek'}}})
		.bind('sortEnd', function(e) {
			$('#timetable tr:even').addClass('even').removeClass('odd');
			$('#timetable tr:odd').addClass('odd').removeClass('even');
			})
		.trigger('sortEnd');
	
	});

//============================================================
//save the site variable out

w.freshfit = s;

//============================================================
})(jQuery, window);
