

$(document).ready(function() {

	// Reject Old Internet Explorer Versions from JS enhancements
	if (navigator.appName == 'Microsoft Internet Explorer') {
		var ieVersion = -1;
		var ua = navigator.userAgent;
		var re  = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
		if (re.exec(ua) != null) {
			ieVersion = parseFloat( RegExp.$1 );
		}
		if (ieVersion > 0 && ieVersion < 9) {
			return; // EXIT
		}
	}
	
	
	// Temporary Fix: Only iPad and iPhone get JS enhancements (because of Safari Mac bug with audio not stopping correctly)
	if (RegExp(" AppleWebKit/").test(navigator.userAgent) && RegExp(" Mobile/").test(navigator.userAgent)) {

		// Detect iPhone or iPad
		if (RegExp("iPhone").test(navigator.userAgent) || RegExp("iPad").test(navigator.userAgent)) {
			browser.init();
			grid.init();
			list.init();
			expander.init();
		}		
	}


});







// EVENT HANDLER ================================


function clickHandlerForGrid(event) {
	var sample = $(event.target).parents('li')[0];
	if (sample) {
		grid.play(sample);		
	}
	return false;
}



function clickHandlerForPlayButtonsInList(event) {
	var sample = $(event.target).parents('li')[0];
	if (sample) {
		list.play(sample);		
	}
	return false;	
}


function clickHandlerForExpander(event) {
	var group = $(this).parent("."+expander.CSS_CLASS_EXPANDER_GROUP)[0];
	expander.toggleGroup(group);
	return false;
}






// BROWSER ================================ 


var browser = {

    CSS_CLASS_BROWSER_JS: "browser-js",
    CSS_CLASS_BROWSER_MAC: "browser-mac",
    CSS_CLASS_BROWSER_WINDOWS: "browser-windows",
    CSS_CLASS_BROWSER_IOS: "browser-ios",
    CSS_CLASS_BROWSER_IPHONE: "browser-iphone",
    CSS_CLASS_BROWSER_IPAD: "browser-ipad",
    CSS_CLASS_BROWSER_SAFARI: "browser-safari",
    CSS_CLASS_BROWSER_FIREFOX: "browser-firefox",
    CSS_CLASS_BROWSER_CHROME: "browser-chrome",
    CSS_CLASS_BROWSER_IE: "browser-ie",
    CSS_CLASS_BROWSER_VIDEO: "browser-video",
    CSS_CLASS_BROWSER_H264: "browser-h264",


	mac: false,
	windows: false,
    ios: false,
    iphone: false,
    ipad: false,
	safari: false,
	firefox: false,
	chrome: false,
	ie: false,
	video: false,
	h264: false,

	
	init: function() {

    	var element = $("html");
		
		// Detect JavaScript
        element.addClass(this.CSS_CLASS_BROWSER_JS);

		// Detect Mac
        if (RegExp("Macintosh").test(navigator.userAgent)) {
        	this.mac = true;
        	element.addClass(this.CSS_CLASS_BROWSER_MAC);        
        }
        // Detect Windows
        else if (RegExp("Windows").test(navigator.userAgent)) {
        	this.windows = true;
        	element.addClass(this.CSS_CLASS_BROWSER_WINDOWS);
        }
        // Detect iOS
        else if (RegExp(" AppleWebKit/").test(navigator.userAgent) && RegExp(" Mobile/").test(navigator.userAgent)) {
			this.ios = true;
			element.addClass(this.CSS_CLASS_BROWSER_IOS);
			
			// Detect iPhone
			if (RegExp("iPhone").test(navigator.userAgent)) {
				this.iphone = true;
				element.addClass(this.CSS_CLASS_BROWSER_IPHONE);
			}
			// Detect iPad
			else if (RegExp("iPad").test(navigator.userAgent)) {
				this.ipad = true;
				element.addClass(this.CSS_CLASS_BROWSER_IPAD);
			}
        }
        
		// Detect Safari
        if (RegExp(" Safari/").test(navigator.userAgent)) {
        	this.safari = true;
        	element.addClass(this.CSS_CLASS_BROWSER_SAFARI);
		}
		// Detect Firefox
		else if (RegExp("Firefox").test(navigator.userAgent)) {
        	this.firefox = true;
        	element.addClass(this.CSS_CLASS_BROWSER_FIREFOX);
		}
		// Detect IE
		else if (RegExp("MSIE").test(navigator.userAgent)) {
        	this.ie = true;
        	element.addClass(this.CSS_CLASS_BROWSER_IE);
		}

		// Detect Chrome
		if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1) {
        	this.chrome = true;
        	element.addClass(this.CSS_CLASS_BROWSER_CHROME);
        	this.safari = false;
        	element.removeClass(this.CSS_CLASS_BROWSER_SAFARI);
		}

		// Detect video support
		var v = document.createElement('video');
		if (!!(v.canPlayType && v.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"').replace(/no/, ''))) {
			this.video = true;
			this.h264 = true;
			element.addClass(this.CSS_CLASS_BROWSER_VIDEO);
			element.addClass(this.CSS_CLASS_BROWSER_H264);
		}
		return;
	}
}







// GRID ================================ 

var grid = {
	CSS_CLASS_FOR_PLAYING: "playing",
	CSS_SELECTOR_FOR_GRID: ".samples ul",
	COL_WIDTH: 250,
	ROW_HEIGHT: 160,
	NUMBER_OF_COLS: 3,
	PLAYER_WIDTH: 730,
	
	grid: undefined,
	player: undefined,
	samples: [],
	urls: [],
	aspectRatios: [],
	titles: [],
	infos: [],
	descriptions: [],

	gridWidth: undefined,
	gridHeight: undefined,
	
	indexOfCurrentlyPlayingSample: undefined, // index of the currently playing sample for the samples and url arrays
	
	init: function() {
		
		// Init properties
		this.grid = $(this.CSS_SELECTOR_FOR_GRID)[0];

		var jQSamples = $(this.grid).children('li');
		for (var i=0; i<jQSamples.length; ++i) {
			
			// Samples <li>
			this.samples.push(jQSamples[i]);
			
			// Links <a>
			var link = $(jQSamples[i]).children('a');
			
			// Video URLs <a href=''>
			var url = link.attr('href');
			this.urls.push(url);
			
			// Aspect Ratios <a class='aspect-ratio-235'>
			var aspectRatio = link.attr('class');
			if (aspectRatio) {
				aspectRatio = parseInt(aspectRatio.replace(/\D/g,''), 10)/100;
			}
			else {
				aspectRatio = 16/9;
			}
			this.aspectRatios.push(aspectRatio);
			
			// Titles
			var title = $(jQSamples[i]).children('h3').html();
			this.titles.push(title);
			
			// Infos
			var info = $(jQSamples[i]).children('.info').html();
			this.infos.push(info);
			
			// Descriptions
			var description = $(jQSamples[i]).children('.description').html();
			this.descriptions.push(description);
		}
		
		// Event handlers
		$(this.grid).bind('click', clickHandlerForGrid);


		// Initiate grid layout
		for (var i=0; i<this.samples.length; ++i) {
			var col = i % this.NUMBER_OF_COLS;
			var row = Math.floor(i / this.NUMBER_OF_COLS);
			$(this.samples[i]).css('left', col * this.COL_WIDTH);
			$(this.samples[i]).css('top', row * this.ROW_HEIGHT);
		}
		this.gridWidth = this.NUMBER_OF_COLS * this.COL_WIDTH;
		this.gridHeight = Math.ceil(this.samples.length / this.NUMBER_OF_COLS) * this.ROW_HEIGHT;
		$(this.grid).css('height', this.gridHeight);
		$(this.grid).css('width', this.gridWidth);		

		// Update layout
		this.updateDom();
	},
	
	isPlaying: function() {
		if (this.indexOfCurrentlyPlayingSample === undefined) {
			return false;
		}
		else {
			return true;
		}
	},
	
	play: function(theSampleNode) {
		// Find index of sample
		var i;
		for (i=0; i<this.samples.length; ++i) {
			if (theSampleNode === this.samples[i]) {
				break;
			}
		}

		// Close the filmography list player
		list.stop();
		
		// Is this sample already playing?
		if (i === this.indexOfCurrentlyPlayingSample) {
			// Stop player
			this.stop();
		}
		// Else
		else {
			// Stop old player
			this.stop();

			// Update data
			this.indexOfCurrentlyPlayingSample = i;

			// Create new player
			this.createPlayer();
			
			// Workaround for iPad: Start loading otherwise another tap is required
		 	if (browser.ipad) {
	 			$(this.player).find('video')[0].load();
			}
		}

		// Update layout
		this.updateDom();
	},
	
	stop: function() {
		if (this.indexOfCurrentlyPlayingSample === undefined) return;	
	
		// Stop playback and loading
		var videoElement = $(this.player).find('video')[0];
		if (videoElement) {
			if (videoElement.pause) {
				videoElement.pause();
			}
			videoElement.src = "";
		}
	
		// Update data
		this.indexOfCurrentlyPlayingSample = undefined;
		
		// Remove player
		this.removePlayer();
		
		// Update layout
		this.updateDom();
	},
	
	createPlayer: function() {
		var width = this.PLAYER_WIDTH;
		var height = Math.round(this.PLAYER_WIDTH / this.aspectRatios[this.indexOfCurrentlyPlayingSample]);
		var html = ""
			+ "<div class='player'> \n"
				+ video.getHtml(this.urls[this.indexOfCurrentlyPlayingSample], width, height)
				+ "<button onclick='grid.stop()'>Close</button> \n"
				+ "<div class='caption'> \n"
					+ "<h3>"+this.titles[this.indexOfCurrentlyPlayingSample]+"</h3> \n"
					+ "<div class='info'>"+this.infos[this.indexOfCurrentlyPlayingSample]+"</div> \n"
					+ "<div class='description'>"+this.descriptions[this.indexOfCurrentlyPlayingSample]+"</div> \n"
				+ "</div> \n"
			+ "</div> \n"
			+ "";
		$(this.grid).after(html);
		this.player = $('.player')[0];
		
		// Load additional info
		//$('.player .info').load(this.urls[this.indexOfCurrentlyPlayingSample]+"/info.html");
		
	},
	
	removePlayer: function() {
		$(this.player).remove();
		this.player = undefined;
	},
	
	updateDom: function() {
		
		// Layout samples
		for (var i=0; i<this.samples.length; ++i) {
			// CSS classes for currently playing sample
			if (i === this.indexOfCurrentlyPlayingSample) {
				$(this.samples[i]).addClass(this.CSS_CLASS_FOR_PLAYING);
			}
			// CSS classes for other samples
			else {
				$(this.samples[i]).removeClass(this.CSS_CLASS_FOR_PLAYING);
			}
		}
		
		// Layout grid
		if (this.indexOfCurrentlyPlayingSample !== undefined) {
			$(this.grid).addClass(this.CSS_CLASS_FOR_PLAYING);
		}
		else {
			$(this.grid).removeClass(this.CSS_CLASS_FOR_PLAYING);
		}

		// Layout player
		//$(this.player).css('min-height', this.gridHeight-20);
	}
}


















// LIST ================================ 


var list = {
	
	PLAYER_WIDTH: 480,
	
	player: undefined,
	samples: [],
	urls: [],
	aspectRatios: [],
	titles: [],
	infos: [],

	gridWidth: undefined,
	gridHeight: undefined,
	
	indexOfCurrentlyPlayingSample: undefined, // index of the currently playing sample for the samples and url arrays
	
	
	init: function() {

		// Wider video on iPhone
		if (browser.iphone) {
			this.PLAYER_WIDTH = 730;
		}
		
		// Init properties
		var jQSamples = $('.filmography ol li');
		for (var i=0; i<jQSamples.length; ++i) {
			
			// Samples <li>
			this.samples.push(jQSamples[i]);
			
			// Links <a>
			var link = $(jQSamples[i]).find('.play-button a');
			
			// Video URLs <a href=''>
			var url = link.attr('href');
			this.urls.push(url);
			
			// Aspect Ratios <a class='aspect-ratio-235'>
			var aspectRatio = link.attr('class');
			if (aspectRatio) {
				aspectRatio = parseInt(aspectRatio.replace(/\D/g,''), 10)/100;
			}
			else {
				aspectRatio = 16/9;
			}
			this.aspectRatios.push(aspectRatio);
		}
		
		// Event handlers
		$(".filmography li .play-button").bind("click", clickHandlerForPlayButtonsInList);

		// Update layout
		this.updateDom();
	},
	
	play: function(theSampleNode) {

		// Find index of sample
		var i;
		for (i=0; i<this.samples.length; ++i) {
			if (theSampleNode === this.samples[i]) {
				break;
			}
		}
		
		// Close the sample grid player
		grid.stop();
		
		// Is this sample already playing?
		if (i === this.indexOfCurrentlyPlayingSample) {
			// Stop player
			this.stop();
		}
		// Else
		else {
			// Stop old player
			this.stop();
			
			// Update data
			this.indexOfCurrentlyPlayingSample = i;
			
			// Create new player
			this.createPlayer();
			
			// Workaround for iPad: Start loading otherwise another tap is required
		 	if (browser.ipad) {
	 			$(this.player).find('video')[0].load();
			}
		}

		// Update layout
		this.updateDom();
	},
	
	stop: function () {
		if (this.indexOfCurrentlyPlayingSample === undefined) return;	
	
		// Stop playback and loading
		
		var videoElement = $(this.player).find('video')[0];
		if (videoElement) {
			if (videoElement.pause) {
				videoElement.pause();
			}
			videoElement.src = "";
		}
		
	
		// Update data
		this.indexOfCurrentlyPlayingSample = undefined;
		
		// Remove player
		this.removePlayer();
		
		// Update layout
		this.updateDom();
	},


	createPlayer: function() {
		var width = this.PLAYER_WIDTH;
		var height = Math.round(this.PLAYER_WIDTH / this.aspectRatios[this.indexOfCurrentlyPlayingSample]);
		var html = ""
			+ "<div class='player'>"
			+ video.getHtml(this.urls[this.indexOfCurrentlyPlayingSample], width, height)
			+ "</div>"
			+ "";
		$(this.samples[this.indexOfCurrentlyPlayingSample]).contents().last().after(html);
		this.player = $('.filmography .player')[0];
	},
	
	removePlayer: function() {
		if (this.player) {
			$(this.player).remove();
			this.player = undefined;
		}
	},

	
	updateDom: function() {
		// Layout samples
		for (var i=0; i<this.samples.length; ++i) {
			// CSS classes for currently playing sample
			if (i === this.indexOfCurrentlyPlayingSample) {
				$(this.samples[i]).addClass('playing');
			}
			// CSS classes for other samples
			else {
				$(this.samples[i]).removeClass('playing');
			}
		}
		
		// Enlarge or shrink expander box
		expander.updateDom();
	}
}



















// EXPANDER ================================ 


var expander = {
	
	CSS_CLASS_EXPANDER_GROUP: 'expander',
	CSS_CLASS_EXPANDER_HEADLINE: 'expander-headline',
	CSS_CLASS_EXPANDER_CONTENT: 'expander-content',
	CSS_CLASS_COLLAPSED: 'collapsed',
	
	groups: [], //contains element, headlineElement, contentElement, isCollapsed, height for each group
	
	init: function() {
		// Find groups and init properties
		var jQGroups = $("."+this.CSS_CLASS_EXPANDER_GROUP);
		for (var i=0; i<jQGroups.length; ++i) {	
			var element = jQGroups[i];
			var headlineElement = $(element).children("."+this.CSS_CLASS_EXPANDER_HEADLINE)[0];
			var contentElement = $(element).children("."+this.CSS_CLASS_EXPANDER_CONTENT)[0];
			var isCollapsed = $(element).hasClass(this.CSS_CLASS_COLLAPSED);
			this.groups.push({
				element: element,
				headlineElement: headlineElement,
				contentElement: contentElement,
				isCollapsed: isCollapsed
			});
		}
		// Bind event handlers
		$('.'+this.CSS_CLASS_EXPANDER_GROUP+'.'+this.CSS_CLASS_COLLAPSED+' .'+this.CSS_CLASS_EXPANDER_HEADLINE).bind('click', clickHandlerForExpander);
		// Update DOM
		this.updateDom();
	},
	
	getGroupObjectForGroupElement: function(theGroupElement) {
		for (var i=0; i<this.groups.length; ++i) {
			if (theGroupElement === this.groups[i].element) {
				return this.groups[i];
			}
		}
	},
	
	toggleGroup: function(theGroupElement) {
		var group = this.getGroupObjectForGroupElement(theGroupElement);
		if (group.isCollapsed) {
			// Expand the group
			group.isCollapsed = false;
		}
		else {
			/* COLLAPSING CURRENTLY DISABLED */
			/* TO ENABLE IT AGAIN, YOU ALSO NEED TO ADJUST THE EVENT HANDLER BINDING IN THE INIT METHOD */
			/*
				// Collapse the group
				group.isCollapsed = true;
				// Stop video if necessary
				list.stop();
			*/
		}
		this.updateDom();
	},
	
	updateDom: function() {
		for (var i=0; i<this.groups.length; ++i) {
			if (this.groups[i].isCollapsed) {
				// Collapsed
				$(this.groups[i].element).addClass(this.CSS_CLASS_COLLAPSED);
			}
			else {
				// Expanded
				$(this.groups[i].element).removeClass(this.CSS_CLASS_COLLAPSED);
			}
		}
	}
}



















// VIDEO ================================ 

var video = {
	

	/* 	
		Expected File Structure is a folder for each video with the following files:
		- index.php as fallback for non-JS browsers
		- thumbnail.jpg an image for the grid
		- video%20-%20Computer.m4v
		- video%20-%20iPhone.m4v for iPhones and other mobile devices
		- video.jpg a poster image
			
	*/
	
	FILENAME_VIDEO: "video%20-%20iPhone.m4v", // using smaller version as well for better performance
	FILENAME_VIDEO_SMALL: "video%20-%20iPhone.m4v",
	FILENAME_VIDEO_POSTER: "video.jpg",

	
	getHtml: function(theFolder, theWidth, theHeight) {

		var code = '';
		
		// Native Video (H264 only)
		// Hack: not for Google Chrome because of weird bugs (native UI is disappearing, and video is loaded twice unless there is a flash fallback within <video> tags
		if (browser.h264 && !browser.chrome) { 
			code = '' +
				'<video width="'+theWidth+'" height="'+theHeight+'" poster="'+theFolder+this.FILENAME_VIDEO_POSTER+'" controls autoplay> \n' +
				'<source src="'+theFolder+this.FILENAME_VIDEO+'" type="video/mp4"> \n' +
				'</video> \n';
		}
		// Flash Video Fallback
		else {
			code = this.getHtmlForFlashVideo(theFolder+this.FILENAME_VIDEO, theWidth, theHeight) + " \n";
		}
			
		// Workaround for iPad: Use different HTML code because of an iPad bug. Only one source must be specified otherwise video playback 'chokes'.
	 	if (browser.ipad) { 
			code = "<video width='"+theWidth+"' height='"+theHeight+"' src='"+theFolder+this.FILENAME_VIDEO_SMALL+"' controls autoplay></video> \n";
		}

		
		return code;
	},
	
	
	
	getHtmlForFlashVideo: function(theVideoUrl, theWidth, theHeight) {	

		var FLASH_PLAYER_URL = '/code/jwplayer-5.5/player.swf';
		var SKIN_URL = '/code/jwplayer-5.5/skins/glow.zip';
		var absoluteVideoUrl = this.getAbsoluteUrl(theVideoUrl);

		// Flash interprets the video source URL as relative to the SWF file.
		// Therefore all URLs have to be converted to absolute URLs with protocol and domain
		// Known issue: Only works online

		var code = '' +
			'<object ' +
			'    classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" ' +
			'    codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=10,0,0,0" ' +
			'    width="'+theWidth+'" ' +
			'    height="'+theHeight+'"> \n' +
			'  <param name="allowScriptAccess" value="always"> \n' +
			'  <param name="allowFullScreen" value="true"> \n' +
			'  <param name="movie" value="'+FLASH_PLAYER_URL+'"> \n' +
			'  <param name="flashvars" value="file='+absoluteVideoUrl+'&autostart=true&controlbar=over&skin='+SKIN_URL+'"> \n' +
			'  <param name="quality" value="high"> \n' +
			'  <param name="bgcolor" value="#000000"> \n' +
			'  <embed ' +
			'    src="'+FLASH_PLAYER_URL+'" ' +
			'    flashvars="file='+absoluteVideoUrl+'&autostart=true&controlbar=over&skin='+SKIN_URL+'" ' +
			'    quality="high" ' +
			'    bgcolor="#000000" ' +
			'    width="'+theWidth+'" ' +
			'    height="'+theHeight+'" ' +
			'    allowScriptAccess="always" ' +
			'    allowFullScreen="true" ' +
			'    type="application/x-shockwave-flash" ' +
			'    pluginspage="http://www.adobe.com/go/getflashplayer" ' +
			'  > \n' +
			'  </embed> \n' +
			'</object> \n';

    			
		return code;
	},
	


	getAbsoluteUrl: function(theUrl) {
		var url;
		if (theUrl.indexOf('http://') === 0) {
			// theUrl is an absolute address with protocol and domain
			url = theUrl;
		}
		else if (theUrl.indexOf('/') === 0) {
			// theUrl is an absolute address on same domain
			url = window.location.hostname + theUrl;
		}
		else {
			// theUrl is a relative address
			url = window.location.href.substr(0, window.location.href.lastIndexOf("/")) + "/" + theUrl;
		}
		return url;
	}


}





