// ----------------------------------------------------------------------------
// Use a stub object to prevent errors in IE from using console.log() etc.
// ----------------------------------------------------------------------------

(function(){
	// Prevent stray debugging calls from erroring when firebug isn't present
	if (!('console' in window) || !('firebug' in console)) {
		var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
		window.console = {};
		for (var i=0; i<names.length; ++i) {
			window.console[names[i]] = function() {}
		}
	}
})();

// ----------------------------------------------------------------------------
// Extensions to the prototype framework (inspired by jQuery 1.2.3)
// ----------------------------------------------------------------------------

(function(){
	var newMethods = {
		visible: function(element) {
			return $(element).getStyle('display') != 'none';
		},
		show: function(element){
			$(element).setStyle({ display: $(element).oldblock || '' });
			if ($(element).getStyle('display') == 'none') {
				var newElement = document.createElement($(element).tagName);
				$$('body').first().insert({bottom: newElement});
				$(element).setStyle({ display: $(newElement).getStyle('display')});
				$(newElement).remove();
				if ($(element).getStyle('display') == 'none') $(element).setStyle({ display: 'block'});
			}
			return element;
		},
		hide: function(element){
			$(element).oldblock = $(element).oldblock || $(element).getStyle("display");
			$(element).setStyle({display: 'none'});
			return element;
		}
	};
	Element.addMethods(newMethods);
})();


// ----------------------------------------------------------------------------
// Hide any elements with a class of 'jsHide' as the page loads
// ----------------------------------------------------------------------------

(function(){
	// See: http://yuiblog.com/blog/2007/06/07/style/
	function addCss(cssCode) {
		var styleElement = document.createElement("style");
		styleElement.type = "text/css";
		if (styleElement.styleSheet) {
			styleElement.styleSheet.cssText = cssCode;
		} else {
			styleElement.appendChild(document.createTextNode(cssCode));
		}
		document.getElementsByTagName("head")[0].appendChild(styleElement);
	}
	addCss(".jsHide { display:none; }");
})();


// ----------------------------------------------------------------------------
// Use unobtrusive Javascript as an accessible replacement for target="_blank"
// to optionally open links marked with rel="external" in a new browser window
// ----------------------------------------------------------------------------

function ExternalLink(el) {
	el.observe('click',function(e){
		window.open(e.findElement('a').href, '_blank');
		e.stop();
	});
}


// ----------------------------------------------------------------------------
// Just a convenience reference to this short browser sniffing snippet
// ----------------------------------------------------------------------------

Prototype.Browser.IE6 = /MSIE 6/i.test(navigator.userAgent);


// ----------------------------------------------------------------------------
// Disclaimer Page Controller Object
// ----------------------------------------------------------------------------

var disclaimerPage = new DisclaimerPage();
function DisclaimerPage() {}

DisclaimerPage.prototype.init = function() {
	// Look for the paperId select and change colours on change
	var select = $('paperId');

	if (!select) return;

	select.observe('change', function(e) {
		var colour = select.options[select.selectedIndex].text.toLowerCase();
		// DJS 20100430 - there's a new '-select-' option - we need to map this to 'smooth' colour
		if (colour == '-select-') {
			document.body.className = 'smooth';
		} else if (document.body.className != colour) {
			document.body.className = colour;
		}
	});
}


// ----------------------------------------------------------------------------
// Home Page Controller Object
// ----------------------------------------------------------------------------

var homePage = new HomePage();
function HomePage() {}

HomePage.prototype.init = function() {
	this.headerArea = $('header');
	if (!this.headerArea) return;
	
	this.initBanner();
	this.initPortal();
	this.initSettings();
	this.initAddToThisPage();
}

HomePage.prototype.initBanner = function() {
	// Hook up the "Your Settings" and "Add to this page" tabs
	var bannerTabs = $$('#userSettings ul li');
	if (!bannerTabs) return;

	bannerTabs.each(function(tab){
		tab.observe('click',this.switchBanner.bind(this, tab.className));
	}.bind(this));

	// Hook up the "Your Rizla" tab and "amend your settings" link
	var yourRizlaTab = this.headerArea.down('ul .yourRizlaHome');
	var amendYourSettingsLink = $('amendYourSettings');
	if (!yourRizlaTab || !amendYourSettingsLink) return;

	yourRizlaTab.observe('click',this.switchBanner.bind(this,'mainPromo'));
	amendYourSettingsLink.observe('click',this.switchBanner.bind(this,'yourSettings'));

	// Get references to the banner content areas
	this.mainPromo = $('mainPromoContent');
	this.yourSettings = $('yourSettingsContent');
	this.addToThisPage = $('addToThisPageContent');
	if (!this.mainPromo || !this.yourSettings || !this.addToThisPage) return;
	
	// And collect them into an array for ease of use in this.switchBanner()
	this.bannerDivs = [];
	this.bannerDivs.push(this.mainPromo);
	this.bannerDivs.push(this.yourSettings);
	this.bannerDivs.push(this.addToThisPage);
}

HomePage.prototype.initPortal = function() {
	this.portal = new Portal('#content .widgetColumn', { url:'/ajax/modules/index.php'});
}

HomePage.prototype.initSettings = function() {
	if (!this.yourSettings) return;
	
	this.colourOptions = [];
	this.headerOptions = [];

	
	// Clicking the packs changes the colour scheme of the page.
	this.settingsPacks = this.yourSettings.select('.chooseColourPacks .pack');
	if (!this.settingsPacks) return;

	this.settingsPacks.each(function(el){
		var label = el.down('label');
		if (label) label.setStyle({ cursor:'pointer' });

		var matches = el.className.match(/pack ([a-z0-9]+)/i);
		var colour = (matches.length == 2) ? matches[1] : '';

		if (colour) this.colourOptions.push(colour);
		el.observe('click',this.switchColour.bind(this,colour));
	}.bind(this));
	

	// Clicking the images changes the header image at the top of the page.
	this.settingsImages = this.yourSettings.select('.chooseImage .pictureFrame');
	if (!this.settingsImages) return;

	this.settingsImages.each(function(el){
		el.setStyle({ cursor:'pointer' });

		var matches = el.className.match(/image pictureFrame ([a-z0-9]+)/i);
		var header = (matches.length == 2) ? matches[1] : '';

		if (header) this.headerOptions.push(header);
		el.observe('click',this.switchHeader.bind(this,header));
	}.bind(this));


	// Hook up the "Save your settings" button to switch back to the main promo.
	var closeBtn = this.yourSettings.down('.btnClose');
	if (!closeBtn) return;
	closeBtn.observe('click',this.switchBanner.bind(this,'mainPromo'));

	// Hide change location form until "change location" link is clicked.
	var yourLocationDetails = this.yourSettings.down('#jsYourLocationDetails');
	var changeLocationForm = this.yourSettings.down('#jsChangeLocationForm');
	if (!yourLocationDetails || !changeLocationForm) return;

	// Hide the form by default
	changeLocationForm.hide();

	function showChangeLocationForm(e){
		if (e) { e.element().blur(); e.stop(); }
		yourLocationDetails.hide();
		changeLocationForm.show();
	}

	// Show the form if the link is clicked, or if there is already an error present
	var changeLocationLink = yourLocationDetails.down('.jsChangeLocation');
	if (changeLocationLink) changeLocationLink.observe('click', showChangeLocationForm);

	var changeLocationError = changeLocationForm.down('.error');
	if (changeLocationError) showChangeLocationForm();

}

HomePage.prototype.initAddToThisPage = function() {
	if (!this.addToThisPage) return;

	document.observe('widget:added', this.setWidgetSummariesState.bind(this));
	document.observe('widget:removed', this.setWidgetSummariesState.bind(this));
	this.setWidgetSummariesState();
	
	// Hook up the "Reset" button to restore the default set of widgets.
	var restoreDefaultsLink = this.addToThisPage.down('.jsRestoreDefaults');
	if (!restoreDefaultsLink) return;
	restoreDefaultsLink.observe('click',this.restoreDefaultWidgets.bind(this));
	
	// Hook up the "Close" button to switch back to the main promo
	var closeBtn = this.addToThisPage.down('.btnClose');
	if (!closeBtn) return;
	closeBtn.observe('click',this.switchBanner.bind(this,'mainPromo'));
}

HomePage.prototype.setWidgetSummariesState = function() {
	var widgetNames = this.portal.widgets.map(function(w){ return w.name; });
	
	this.widgetSummaries = this.addToThisPage.select('.widgetSummary');
	this.widgetSummaries.each(function(summary) {
		var matches = summary.id.match(/(.*)Summary$/);
		if (matches) {
			var summaryName = matches[1];
			var summaryLink = summary.down('a');
			if (!summaryName || !summaryLink) return;
			
			if (widgetNames.include(summaryName)) {
				summary.addClassName('widgetSummaryDisabled');
				summaryLink.href = summaryLink.href.replace(/(\/add-widget\/)/,'/remove-widget/');
				summaryLink.update('Remove');
			} else {
				summary.removeClassName('widgetSummaryDisabled');
				summaryLink.href = summaryLink.href.replace(/(\/remove-widget\/)/,'/add-widget/');
				summaryLink.update('Add');
			}
		}
	});
}

HomePage.prototype.saveSettings = function() {
	new Ajax.Request('/ajax/', {
		parameters: { 'colour':this.getCurrentColour(), 'image':this.getCurrentHeader() }
	});
}

HomePage.prototype.restoreDefaultWidgets = function(e) {
	if (e) { e.stop(); e.element().blur(); }
	
	if (confirm('Are you sure you want to roll back?')) {
		new Ajax.Request('/ajax/modules/', {
			parameters: { 'action':'restoreDefaultWidgets' },
			onComplete: function() {
				window.location.href = window.location.href;
			}
		});
	}
	
}

HomePage.prototype.getCurrentColour = function() {
	var classes = document.body.className.split(/ +/);
	if (this.colourOptions) {
		var colour = classes.find(function(c){
			return this.colourOptions.include(c);
		}.bind(this));
	} else {
		var colour = classes[0];
	}
	return colour;
}

HomePage.prototype.getCurrentHeader = function() {
	var classes = this.headerArea.className.split(/ +/);
	if (this.headerOptions) {
		var header = classes.find(function(c){
			return this.headerOptions.include(c);
		}.bind(this));
	} else {
		var header = classes[0];
	}
	return header;
}

HomePage.prototype.switchColour = function(className, e) {
	if (e) { e.stop(); e.element().blur(); }

	document.body.className = className;

	this.settingsPacks.each(function(el){
		var input = el.down('input');
		if (input) input.checked = el.hasClassName(className);
	});
	
	this.saveSettings();
	
	console.log('switch colour fired');

	document.fire('colour:changed');
}

HomePage.prototype.switchHeader = function(className, e) {
	if (e) { e.stop(); e.element().blur(); }

	this.headerArea.className = className;

	this.settingsImages.each(function(el){
		var input = el.down('input');
		if (input) input.checked = el.hasClassName(className);
	});
	
	this.saveSettings();
}

HomePage.prototype.switchBanner = function(bannerName, e) {
	if (e) { e.stop(); e.element().blur(); }

	if (!this.isAnimating) {
		this.bannerDivs.each(function(div){
			if (div.id == bannerName + 'Content') {
				if (!div.visible()) new Effect.SlideDown(div,{ queue:'end', duration:0.5, afterFinish:function(){ this.isAnimating = false; }.bind(this) });
			} else {
				if (div.visible()) new Effect.SlideUp(div, { queue:'front', duration:0.5, beforeStart:function(){ this.isAnimating = true; }.bind(this) });
			}
		}.bind(this));
	}
}


// ----------------------------------------------------------------------------
// Product Page Controller Object
// ----------------------------------------------------------------------------

var productPage = new ProductPage();
function ProductPage() {}

ProductPage.prototype.init = function() {
	this.container = $('jsProductDetails');
	if (!this.container) return;

	this.products = this.container.select('.jsProductDetail');
	if (!this.products) return;

	// Moved this into the page as server-side functionality
	/*
	var currentProduct = this.products.find(function(p){ return p.visible() });
	if (!currentProduct) {
		var colour = document.body.className || 'smooth';
		this.setProduct(colour);
	}
	*/
}

ProductPage.prototype.setProduct = function(colour, pack) {
	if (typeof pack == 'undefined') {
		var pack = 'regular';
	}
	var id = 'jsProduct' + this.UCFirst(colour) + this.UCFirst(pack);
	this.products.each(function(el){
		el[(el.id == id) ? 'show':'hide' ]();
	});
}

ProductPage.prototype.UCFirst = function(string) {
	return string.slice(0,1).toUpperCase() + string.slice(1);
}


// ----------------------------------------------------------------------------
// Widget-specific functionality
// ----------------------------------------------------------------------------

// Twizla Widget

function Twizla() {
	this.container = $('twizla');
	if (!this.container) return;

	// Make sure it's only initialised once
	if (this.container.initedAsWidget) return;
	this.container.initedAsWidget = true;

	this.pagination 	= this.container.down('#jsTwizlaPagination');
	this.olderLink 		= this.container.down('#jsTwizlaOlderLink');
	this.newerLink 		= this.container.down('#jsTwizlaNewerLink');
	this.messages 		= this.container.select('.jsTwizlaItem');
	if (!this.olderLink || !this.newerLink || !this.messages) return;
	
	// hide the newer link on page load, cos we always load the most recent
	this.newerLink.hide();
	
	this.olderLink.observe('click', this.cycle.bind(this,  'showOlder'));
	this.newerLink.observe('click', this.cycle.bind(this, 'showNewer'));

	this.position = 0;
	this.cycle(0);
}

Twizla.prototype.cycle = function(direction, e) {
	if (e) { e.stop(); }
	
	// ajax call to get the previous or next items
	new Ajax.Request('/ajax/twizla/view.php',
		{ 
		'parameters': { 'action': direction },
		onSuccess : function(transport) {
			// update the tweets in the widget with returned data
			var data = transport.responseJSON;

			// Hide or show the Older / Newer links
			if ( !data['hasOlder'] ) {
				this.olderLink.hide();
			} else {
				this.olderLink.show();
			}
			if ( !data['hasNewer'] ) {
				this.newerLink.hide();
			} else {
				this.newerLink.show();
			}
			
			// Update the pagination string
			this.pagination.innerHTML	= data['paginationString'];
			
			// Update the news items
			var news_items 			= data['newsItems'];
			for (var i=0; i < 3; i++) {
				
				var container = this.messages[i].up('.jsTwizlaItemWrap');
				
				if ( news_items[i] ) {
				
					// news_items[i][0] is the content
					// news_items[i][1] is the recency
					// news_items[i][2] is the createdByName
				
					container.show();
					
					// Update the text
					this.messages[i].innerHTML = news_items[i][0];
					// Update the "time ago"
					this.messages[i].up('.jsTwizlaItemWrap').down('.when').innerHTML = news_items[i][1] + ' by ' + news_items[i][2] ;
					
				} else {
					// if we have less than 3 items then we need to hide sometimes 
					container.hide();
				}
				
				// check if is a "rizla" twizla. if not, it's user generated so add classname
				if (news_items[i][2] != "Rizla" ) {
					container.addClassName('publicTweet');
				} else {
					container.removeClassName('publicTweet');
				}
			}	
		}.bind(this)
	});
	
	homePage.portal.updateColumnHeights();
}

// Flash link calls this
function gotoTwizla() {
	var container = $('twizla');
	
	if (!container) { 
		new Overlay().load('/add-widget/?id=5');
	} else { 
		container.scrollIntoView(true);

	}
}

function gotoMotoGP() {
	var container = $('motoGP');
	
	if (!container) { 
		new Overlay().load('/add-widget/?id=16');
	} else { 
		container.scrollIntoView(true);

	}
}

function openMotoGPGame() {
	new Overlay().load('/game-time/?game=moto-gp-giveaway', {'displayContentFlush':true} );
}

// Moto GP widget
function MotoGP() {
	this.container = $('motoGP');
	if (!this.container) return;
	
	// foreground image transparency for IE6
	if (Prototype.Browser.IE6) {
		$('moto-g-map-nav').select('img').each(function(navIcon){
			navIcon.src= "/javascripts/lib/sense/assets/img/common/spacer.gif";
		});
	}
	
	// Scrolling news items
	this.selectedItem = 0;
	this.itemsWrap = $('moto-news-feed').down('#scrollingItemsWrap');
	this.itemDivs = this.itemsWrap.select('.newsItem');
	this.timeoutId = setTimeout(this.showPrevNextNews.bind(this, null, 1), 4000);
	
	// Google map
	this.races = $$('#moto-g-map-nav .raceDetails');
	this.races.each(function(race, index){
		if (race.hasClassName('current')) this.currRaceKey = index;
	}.bind(this));
	this.initPrevNextTrackListeners();
	this.initGMap();
}

MotoGP.prototype.initPrevNextTrackListeners = function() {
	$$('#moto-g-map-nav img').each(function(trackNav){
		trackNav.stopObserving();
		trackNav.observe('click', this.showPrevNextTrack.bind(this));
	}.bind(this));
}

MotoGP.prototype.initGMap = function(){
	
	var latitude 	= this.races[this.currRaceKey].down('.latitude').innerHTML;
	var longitude 	= this.races[this.currRaceKey].down('.longitude').innerHTML;
	//console.log('latitude: '+latitude+' longitude: '+longitude);
	
	if (GBrowserIsCompatible()) {
		
		var currLoc = new GLatLng(latitude, longitude);
		var map 	= new GMap2(document.getElementById("map_canvas"));
		map.setCenter(currLoc, 15);
		map.setMapType(G_SATELLITE_MAP);
		
		var marker = new GMarker(currLoc, this.mapIcon());
		map.addOverlay(marker);
		
		// Offset the location so that the map will be roughly
		// centered on the marker middle, rather than the marker bottom (the point)
		var locA = marker.getLatLng();
		var locB = map.fromLatLngToContainerPixel(locA);
		locB.x += 0;
		locB.y -= 25;
		locB = map.fromContainerPixelToLatLng(locB);
		map.panTo(locB);

	}
}

MotoGP.prototype.showPrevNextTrack = function(e) {
	if (e) { e.stop(); e.element().blur(); }
		
	var origKey = this.currRaceKey;
	if ( e.target.hasClassName('fl') ) {
		// Nav Left
		this.currRaceKey = (this.currRaceKey > 0) ? this.currRaceKey-1 : this.races.size()-1;
	} else {
		// Nav Right
		this.currRaceKey = (this.currRaceKey < this.races.length-1) ? this.currRaceKey+1 : 0;
	}
	
	// Hide and show
	this.races[origKey].removeClassName('current');
	this.races[this.currRaceKey].addClassName('current');
	
	this.initPrevNextTrackListeners();
	this.initGMap();
}

MotoGP.prototype.showPrevNextNews = function(e, dir) {
	if (e) { e.stop(); e.element().blur(); }
	
	var min = 0;
	var max = this.itemDivs.size()-1;
	
	this.selectedItem += dir;
	if (this.selectedItem > max) this.selectedItem = min;
	if (this.selectedItem < min) this.selectedItem = max;
	
	var newY = -(this.selectedItem * 60) + 7;
	var options = { seconds:0.7, style:{ top : newY+"px" }, transition:Tween.easing.elastic.easeOut, onEnd:this.showNextNewsLoop() };
	
	new Tween(this.itemsWrap, options);
}

MotoGP.prototype.showNextNewsLoop = function(){
	this.resetNextItemLoop();
	this.timeoutId = setTimeout(this.showPrevNextNews.bind(this, null, 1), 5000);
}

MotoGP.prototype.resetNextItemLoop = function(){
	if (this.timeoutId) {
		clearInterval(this.timeoutId);
		this.timeoutId = null;
	}
}

MotoGP.prototype.mapIcon = function() {
	var icon = new GIcon();

	icon.image = '/images/maps/moto-gp-icon.png';
	icon.shadow = '/images/maps/marker-shadow.png';
	icon.iconSize = new GSize(45, 66);
	icon.shadowSize = new GSize(70, 69);
	icon.iconAnchor = new GPoint(22, 66);
	icon.infoWindowAnchor = new GPoint(22, 66);

	return icon;
}


// Invisible Players Widget

function InvisiblePlayers() {
	this.container = $('invisiblePlayers');
	if (!this.container) return;

	// Make sure it's only initialised once
	if (this.container.initedAsWidget) return;
	this.container.initedAsWidget = true;
	
	this.hiddenText = this.container.select('.initially-hidden');
	
	this.initArtists();
	this.initEvents();
	this.initExpandingDiv(null);
}

InvisiblePlayers.prototype.initExpandingDiv = function(e) {
	
	if (e != null) { // User clicked "close"
		e.stop(); e.preventDefault();
		$('IPReadLessWrap').remove();
	}
	// Add "read more" link and hide the text
	this.hiddenText.each(function(hid, index){
		if (index == 0) hid.insert({ before:'<span id="IPReadMoreWrap">... <a href="#" id="IPReadMore" style="color:#fff;">Read more</a></span>' });
		hid.hide();
	});
	$('IPReadMore').observe('click', this.openExpandingDiv.bind(this));
}

InvisiblePlayers.prototype.openExpandingDiv = function(e) {
	e.stop(); e.preventDefault();
	
	// Add the "close" link and show the text
	this.hiddenText.each(function(hid, index){
		hid.show();
		if (index == this.hiddenText.size()-1) hid.insert({ after:'<span id="IPReadLessWrap"><br /><a href="#" id="IPReadLess" style="color:#fff;">Close</a></span>' });
	}.bind(this));
	
	$('IPReadMoreWrap').remove();
	$('IPReadLess').observe('click', this.initExpandingDiv.bind(this));
}

InvisiblePlayers.prototype.initArtists = function() {
	this.artistNavArea = $('jsInvisPlayersArtistNav');
	this.artistBioArea = $('jsInvisPlayersArtistBio');
	if (!this.artistNavArea || !this.artistBioArea) return;
	
	this.artistName = this.artistBioArea.down('#jsInvisPlayersArtistName');
	this.artistText = this.artistBioArea.down('#jsInvisPlayersArtistText');
	this.artistLink = this.artistBioArea.down('#jsInvisPlayersArtistLink');
	if (!this.artistName || !this.artistText || !this.artistLink) return;

	this.artistNavItems = this.artistNavArea.select('.pictureFrame');
	this.artistNavItems.each(function(el,i){
		el.observe('click', this.switchArtist.bindAsEventListener(this, i));
	}.bind(this));
}

InvisiblePlayers.prototype.switchArtist = function(e, i) {
	if (e) { e.element().blur(); e.stop(); }

	this.artistNavItems.each(function(el){
		var span = el.down('.artistSelected');
		if (span) span.remove();
	});
	
	var span = new Element('span').addClassName('artistSelected');
	this.artistNavItems[i].insert(span);

	if (typeof DD_belatedPNG != 'undefined') {
		DD_belatedPNG.fixPng(span);
	}

	var n = i + 1;
	this.artistName.update('Artist name #' + n);
	this.artistText.update(n + " Aliquam aliquet, est a ullamcorper condimentum, tellus nulla fringilla elit, a iaculis nulla turpis sed wisi. Fusce volutpat. Etiam sodales ante id nunc. Proin ornare dignissim lacus.");
	this.artistLink.update('Read all about Artist #' + n + ' here');
}

InvisiblePlayers.prototype.initEvents = function() {
	var tabA = this.container.down('#jsInvisPlayersFestivalTab');
	var listA = this.container.down('#jsInvisPlayersFestivalList');
	if (!tabA || !listA) return;
	
	var tabB = this.container.down('#jsInvisPlayersPartyTab');
	var listB = this.container.down('#jsInvisPlayersPartyList');
	if (!tabB || !listB) return;

	this.festival = {tab:tabA, list:listA};
	this.party = {tab:tabB, list:listB};
	
	this.selectedTabClassName = 'selected';
	
	this.festival.tab.down('a').observe('click',this.showFestivals.bind(this));
	this.party.tab.down('a').observe('click',this.showParties.bind(this));

}

InvisiblePlayers.prototype.showFestivals = function(e) {
	if (e) { e.stop(); }
	this.deactivate(this.party);
	this.activate(this.festival);
}

InvisiblePlayers.prototype.showParties = function(e) {
	if (e) { e.stop(); }
	this.deactivate(this.festival);
	this.activate(this.party);
}

InvisiblePlayers.prototype.activate = function(eventElements) {
	eventElements.tab.addClassName(this.selectedTabClassName);
	eventElements.list.show();
}

InvisiblePlayers.prototype.deactivate = function(eventElements) {
	eventElements.tab.removeClassName(this.selectedTabClassName);
	eventElements.list.hide();
}

// Where Do You Rizla? Widget

function WhereDoYouRizla() {
	this.container = $('whereDoYouRizla');
	if (!this.container) return;

	// Make sure it's only initialised once
	if (this.container.initedAsWidget) return;
	this.container.initedAsWidget = true;

	// Get references to all the DOM elements necessary to init the animation
	this.outer = this.container.down('.thumbnails');
	if (!this.outer) return;
	this.inner = this.outer.down('.inner');
	this.thumbs = this.outer.select('a');
	if (!this.inner || !this.thumbs) return;

	this.initAnimation();

	// Get references to all the DOM elements necessary to init the flash
	this.moreLink = this.container.down('#jsWDYRizlaMore');
	this.flash = $('jsWDYRFullScreen');
	if (!this.moreLink || !this.flash) return;

	this.initFlash();
}

WhereDoYouRizla.prototype.initFlash = function(){
	// Set click handlers on the thumbs and link to open the flash
	this.outer.observe('click',this.toggleFullScreen.bind(this,true));
	this.moreLink.observe('click',this.toggleFullScreen.bind(this,true));

	var closeBtn = this.flash.down('.flashFullClose');
	var uploadBtn = this.flash.down('.flashFullUpload');
	if (!closeBtn || !uploadBtn) return;

	closeBtn.observe('click',this.toggleFullScreen.bind(this,false))
	uploadBtn.observe('click',this.openUploadOverlay.bind(this));

	// Resize the flash when we resize the window to keep it full screen
	Event.observe(window,'resize',this.resizeFlash.bind(this));
	this.resizeFlash();

	// Use position:fixed so we can't scroll away from the flash
	if (Prototype.Browser.IE6) {
		this.scrollFlashHandler = this.scrollFlash.bindAsEventListener(this)
	} else {
		this.flash.setStyle({ position:'fixed' });
	}
}

WhereDoYouRizla.prototype.resizeFlash = function(){
	var head = this.flash.down('.flashFullHead');
	var body = this.flash.down('.flashFullBody');
	var h1 = document.viewport.getHeight()
	var h2 = parseInt(head.getStyle('height'),10) + parseInt(head.getStyle('paddingTop'),10) + parseInt(head.getStyle('paddingBottom'),10);
	body.setStyle({ height:(h1 - h2) + 'px' });
}

WhereDoYouRizla.prototype.scrollFlash = function(){
	var scroll = document.viewport.getScrollOffsets();
	this.flash.setStyle({ top:scroll[1] + 'px' });
	// window.scrollTo(0,0);
}

WhereDoYouRizla.prototype.initAnimation = function(){
	if (!this.thumbs.length) return;

	// Find the width of a thumbnail (plus 1-pixel right margin)
	this.thumbWidth = this.thumbs.first().getWidth() + 1;
	// If elements aren't visible getWidth() returns 0. Correct for this.
	if (this.thumbWidth == 1) this.thumbWidth = (75 + 1);
	// Make sure the thumb container is wide enough to fit one "extra" 
	// thumb hiding off-screen at all times, ready to be animated on.
	// (Otherwise it will wrap underneath since it's a float).
	this.inner.setStyle({ width: (this.thumbWidth * 5) + 'px' });

	// Add some extra styling and start the animation
	this.addReflections();
	this.next();
}

WhereDoYouRizla.prototype.addReflections = function(){
	// Turn the foreground images into background images and 
	// then replace the foreground images with a PNG highlight.
	
	// CSS used elsewhere for this and CSS required by animation 
	// were conflicting, seemed easier to just do this.

	this.thumbs.each(function(el){
		var img = el.down('img');
		el.setStyle({ background:'url('+ img.src +') no-repeat' });
		img.src = '/images/widgets/common/image_reflection_75_75.png';
	});

	// Run PNG fix for IE6, but limit it to these thumbnails
	if (Prototype.Browser.IE6) supersleight.run(this.inner);
}

WhereDoYouRizla.prototype.next = function(){
	// Stop the animation loop, wait for 5 
	// seconds, and then start it up again.
	if (this.intervalId) {
		clearInterval(this.intervalId);
	}
	setTimeout(function(){
		this.intervalId = setInterval(this.animate.bind(this), 50);
	}.bind(this), 5000);
}

WhereDoYouRizla.prototype.animate = function(){
	// Move the thumb container div to the left until 
	// the left-most thumb is off-screen.
	var x = parseInt(this.inner.getStyle('left') || 0, 10) - 4;
	if (x <= (this.thumbWidth * -1)) {
		this.repositionThumb();
		this.next();
		x = 0;
	}
	this.inner.setStyle({ left:x + 'px' });
}

WhereDoYouRizla.prototype.repositionThumb = function(){
	// Move the first thumb to the end in both our 
	// array of element references, and in the DOM.
	var thumbA = this.thumbs.shift();
	var thumbZ = this.thumbs.last();
	thumbZ.insert({ after:thumbA });
	this.thumbs.push(thumbA);
}

WhereDoYouRizla.prototype.toggleFullScreen = function(toggle, e) {
	if (e) { e.stop(); e.element().blur(); }

	// When the flash is open, we need to manually position it for IE6
	if (this.scrollFlashHandler) {
		if (toggle) {
			Event.observe(window,'scroll',this.scrollFlashHandler);
			this.scrollFlashHandler(); // Run it once to set start position
		} else {
			Event.stopObserving(window,'scroll',this.scrollFlashHandler);
		}
	}

	// Open the full-screen gallery
	this.flash[toggle ? 'show':'hide']();

	// Hide any underlying flash
	var gallery = this.flash.down('object, embed');
	$$('object, embed').each(function(el){
		if (el != gallery) el.setStyle({ visibility: toggle ? 'hidden':'visible' });
	}.bind(this));
}

WhereDoYouRizla.prototype.openUploadOverlay = function(toggle, e) {
	if (e) { e.stop(); e.element().blur(); }
	new Overlay().load('/where-do-you-rizla/');
}


// Rolling Weather Widget

function RollingWeather() {
	
	// Url for form requests
	this.changeLocationUrl = '/ajax/locations/change.php';
	
	this.container = $('rollingWeather');
	if (!this.container) return;

	// Make sure it's only initialised once
	if (this.container.initedAsWidget) return;
	this.container.initedAsWidget = true;

	// Add listener to change location form.
	this.changeLocationForm = this.container.down('form');
	if (!this.changeLocationForm) return;

	this.settingsSaveBtn = this.changeLocationForm.down('.jsSettingsSaveBtn');
	if (!this.settingsSaveBtn) return;
	
	// Messy but prevent form from submitting
	// this.changeLocationForm.observe('submit', function(e) {
	// 	e.stop();
	// }.bind(this));
	
	this.settingsSaveBtn.observe('click', this.changeLocation.bind(this));
	
	// Get the necessary DOM references
	this.fiveDayLink = this.container.down('#jsRollingWeather5DayLink');
	this.fiveDayDiv = this.container.down('#jsRollingWeather5DayDiv');
	if (!this.fiveDayLink || !this.fiveDayDiv) return;

	this.fiveDayLink.observe('click',this.toggle5Day.bind(this));
}

RollingWeather.prototype.changeLocation = function(e) {
	if (e) { e.stop(); e.element().blur(); }
	
	var loc = this.changeLocationForm.location.getValue();
	
	if (this.changeLocationUrl && loc) {
		new Ajax.Request(this.changeLocationUrl,{ 
			'parameters': { 'action':'changeWeatherLocation', 'location':loc },
			'onSuccess' : function(transport) {
				// Don't use location.reload() otherwise we risk re-POST warnings
				window.location.href = window.location.href;
			}
		});
	}
}

RollingWeather.prototype.toggle5Day = function(e) {
	if (e) { e.element().blur(); e.stop(); }
	var toggle = this.fiveDayDiv.visible();
	if (toggle) {
		this.fiveDayDiv.hide();
		this.fiveDayLink.removeClassName('showExpanded').addClassName('showCollapsed');
	} else {
		this.fiveDayDiv.show();
		this.fiveDayLink.removeClassName('showCollapsed').addClassName('showExpanded');
	}
}


// Advent Tree Widget

function AdventTree() {
	this.container = $('adventTree');
	if (!this.container) return;

	this.winners = this.container.down('#winnersStrip #winnersStripInner');
	if (!this.winners) return;

	// Nbsp here so the space is accounted for in the width
	var gap = ',&nbsp;'; 
	
	// Wrap the text in a movable wrapper
	this.winnerText = this.winners.innerHTML + gap;
	this.winnerWrap = new Element('div');

	this.winnerWrap.update(this.winnerText);
	this.winners.update(this.winnerWrap);
	
	// Duplicate the text a few times to make sure we can scroll 
	// the full thing off screen at least once without any 
	// right-hand white-space showing, before shifting it back to 
	// its original position again.

	this.outerWidth = this.winners.getWidth();
	this.innerWidth = this.winnerWrap.getWidth();

	var multiples = Math.ceil(this.outerWidth / this.innerWidth) + 1;
	var multiplesText = '';
	
	while (multiples--) multiplesText += this.winnerText;

	this.winnerWrap.update(multiplesText);

	// Start the animation scrolling the text to the left
	this.currentPos = 0;
	this.animate();
}

AdventTree.prototype.animate = function() {
	if (this.currentPos < this.innerWidth) {
		this.currentPos += 1;
		this.winnerWrap.setStyle({ marginLeft: -(this.currentPos) + 'px' });
	} else {
		this.currentPos = 0;
		this.winnerWrap.setStyle({ marginLeft: '0px' });
	}
	this.timeoutId = setTimeout(this.animate.bind(this), 50);
}


// ----------------------------------------------------------------------------
// Flash Movie Dynamic Colouring
// ----------------------------------------------------------------------------

function initFlashMovieColours() {
	// Called on page load, and whenever colour settings are changed.
	// Updates paths of flash movies with a dynamicColoring variable.

	// Colour values includes primary & secondary. Secondary is unused.
	var colourOptions = ['smooth','green','red','silver','blue','white','liquorice'];
	var colourValues = {
		'smooth': 		['008d30','35a647'],
		'green': 		['01754c','009661'],
		'red': 			['d92920','fd4239'],
		'silver': 		['c0c7cb','d8dee2'],
		'blue': 		['00a8e1','48c0e8'],
		'white': 		['e7e7e6','f8f7f5'],
		'liquorice': 	['f28c0d','ffa12d']
	};
	
	function elementColour(el) {
		return (el) ? colourOptions.find(function(c){ return el.hasClassName(c); }) : false;
	}

	var defaultColour = elementColour($(document.body));
	
	$$('object, embed').each(function(el){
		var colour = elementColour(el.up('.widget')) || defaultColour;
		var hexVal = '0x' + colourValues[colour][0];
		if (el.setDynamicColouring) {
			el.setDynamicColouring(hexVal);
		}
	});
}

// Watch for colour:changed events fired by the page
// (also flash:loaded events being fired by the flash
// to tell us when we can call "setDynamicColouring")
document.observe('colour:changed',initFlashMovieColours);
document.observe('flash:loaded',initFlashMovieColours);

// Small wrapper function for the flash movies to call
function flashLoaded() { 
	document.fire('flash:loaded');
}


// --------------------------------------------------------------------------------
// UI Widget Initialisers
// --------------------------------------------------------------------------------

function initFrameworkWidgets() {
	// Framework widgets can be specified just as a string constructor name (in which
	// case a selector of ".jsConstructorName" is presumed) or with config object, 
	// providing a custom selector and/or custom options.
	
	var widgetTypes = [
		{ constructor:'ExternalLink', selector:'a[rel=external]' },
		{ constructor:'Overlay', selector:'a[rel^=overlay]' },
		'AutocompleteSelect',
		'Autocomplete',
		'FlashPlayer'
	];

	widgetTypes.each(function(widgetType){
		// Allow for the two seperate methods of specifying a widget as detailed above.
		var isObj = (typeof widgetType != 'string');
		var constructor = (isObj) ? widgetType.constructor : widgetType;
		var cssSelector = (isObj && widgetType.selector) ? widgetType.selector : '.js' + constructor;
		var options 	= (isObj && widgetType.options) ? widgetType.options : {};
		var initedFlag	= 'initialisedAs' + widgetType;

		// If the widget definition .js file has not been loaded, just return.
		if (typeof window[constructor] == 'undefined') return;

		// Iterate through each DOM element matching the selector and pass it into the constructor.
		$$(cssSelector).each(function(el){
			// Make sure that we only initialise a widget once.
			if (typeof el[initedFlag] == 'undefined') {
				el[initedFlag] = true;
				if (options) {
					new window[constructor](el, options);
				} else {
					new window[constructor](el);
				}
			}
		});
	});
}

// --------------------------------------------------------------------------------
// Mobile Overlay
// --------------------------------------------------------------------------------

// Check for overlay $_GET variable - if exists open overlay
var url = window.location.toString();
var openOverlay = url.toQueryParams().overlay;
document.observe('dom:loaded', function() {
	if (openOverlay=="mobile") { mobileOverlay(); }
});

function mobileOverlay() {
	new Overlay().load('/mobile/', {'contentWidth':700, 'headingText':'Mobile content'});
}

// --------------------------------------------------------------------------------
// PNG fixing for foreground images with class="png" in IE6
// --------------------------------------------------------------------------------

function fixPNGs() {
	if (!Prototype.Browser.IE6) return;
	if (typeof supersleight != 'undefined') {
		$$('.png').each(function(el){
			supersleight.fix(el);
		});
	}
}

// --------------------------------------------------------------------------------
// Event Observers to Initialise Page Content
// --------------------------------------------------------------------------------

function initPage() {
	disclaimerPage.init();
	homePage.init();
	productPage.init();
	// adminPage.init();

	initContent();

	// On the products & heritage pages give focus to the main flash 
	// movie so keyboard nav works without clicking to focus it first
	// (Do this after initContent, since that initialises the flash)
	var el = $('productSelector') ||  $('heritage');
	if (el) {
		var player = el.select('object, embed')[0];
		if (player) player.focus();
	}
	
	// Set up tracker.
	initTracker();
}

function initContent() {
	// Initialise jsFrameWork UI widgets
	initFrameworkWidgets();

	// Initialise Rizla widgets content
	new WhereDoYouRizla();
	new InvisiblePlayers();
	new Twizla();
	new RollingWeather();
	new AdventTree();
	new MotoGP();

	// Update the portal to account for any changes
	// in widget height which may have occurred.
	if (homePage.portal) {
		homePage.portal.updateColumnHeights();
	}
	
	// Run the IE6 PNG fix for any newly added content
	fixPNGs();
}

// Watch for tracking events.
document.observe('event:track', function(event) {
	args = event.memo;
	if (!args || !pageTracker) return;	
	
	pageTracker._trackEvent(args.category, args.action, args.label, args.value);
});

// Register events for ga tracking.
function initTracker() {
	// Register overlay clicks with ga.
	$$('a[rel^=overlay]').each(function(el) {
		// Get url
		label = el.getAttribute('href');
			
		el.observe('click', function() {
			document.fire('event:track', { 
				category: 'overlay',
				action: 'click',
				label: label,
				value: null
			})
		}.bindAsEventListener(this));
	});
}

document.observe('dom:loaded', initPage);
document.observe('dom:updated', initContent);
