/*global $, console */

/* -----------------------------------------------------------------
Uses Crockford's module pattern:
http://ajaxian.com/archives/a-javascript-module-pattern

Also using the "revealing" modification for returning 
public methods and variables.
----------------------------------------------------------------- */


var SOUNDSLIDES = {}; // create global namespace for all Soundslides modules

SOUNDSLIDES.player = function ( init_object ) {
	
	/* -----------------------------------------------------------------
	Example:
	
	init_object = {'container_div': 'container',
		'path': 'test_slideshows/publish_to_web_bundy_click/'};
	
	Required items: container_div, path
	Optional items: width, height, image_path_override
	
	----------------------------------------------------------------- */
	
	var model, load_and_parse_xml, create_initial_elements, time_check, check_for_active_image, 
		check_for_lower_third_event, post_parse, load_audio, change_state, image_update, 
		format_display, counter_update, caption_update, change_slide, center_and_size_slide, 
		trace, sanitize_string, change_lowerthird, change_size;
	
	model = {
		container_div: init_object.container_div,
		current_slide:0,
		current_lowerthird: -1,
		caption_displayed: false,
		credit_displayed: false,
		path: init_object.path,
		path_to_audio: init_object.path,
		image_path_override: init_object.image_path_override,
		url_to_xml: init_object.path + 'soundslide.xml',
		width: 0,
		height: 0,
		slide_width: 0,
		slide_height: 0,
		controls_height: 50,
		slide_array: [],
		meta_dict: {},
		lowerthirds_array: [],
		preload_limit: 3,
		images_loaded: 0,
		playhead_elapsed_ms:0,
		slideshow_type: undefined,
		time_interval: 0,
		state: 'stop',
		upscaling: true,
		nav_style: 'iPad',
		debug:false
	};
	
	
	load_and_parse_xml = function () {
		
		trace( model.url_to_xml );
		
		var node, parameter, value, filename, caption, timing, duration, inpoint, i, name, title;
		
		$.ajax({
			type: "GET",
			url: model.url_to_xml,
			dataType: "xml",
			success: function( xml ) {
				
				/* -----------------------------------------------------------------
				Get the slide show display data into meta_dict
				----------------------------------------------------------------- */

				$(xml).find('item').each(function(){
					
					node = $(this);
					parameter = node.find('parameter').text();
					value = node.find('value').text();

					model.meta_dict[parameter] = value;

					
				});

				trace ( model.meta_dict );

				/* -----------------------------------------------------------------
				Get all the image data and load the images into slide_array
				----------------------------------------------------------------- */

				$(xml).find('slide').each(function(){
					
					node = $(this);
					filename = node.find('file').text();
					caption = node.find('caption').text();
					timing = node.find('timing').text();
					
					model.slide_array.push({ 'filename': filename, 'caption': caption, 'timing': timing });

				});

				//trace( model.slide_array );
				
				/* -----------------------------------------------------------------
				Lowerthirds information into lowerthird_array
				----------------------------------------------------------------- */
				
				$(xml).find('lower_thirds').find('item').each(function(){
					
					node = $(this);
					name = node.find('name').text();
					title = node.find('title').text();
					inpoint = Number ( node.find('inpoint').text() );
					duration = Number ( node.find('duration').text() );
					
					model.lowerthirds_array.push({ 'name': name, 'title': title, 'inpoint':inpoint, 'duration':duration });

				});
				
				trace("lowerthirds_array: " + model.lowerthirds_array);
				
				/* -----------------------------------------------------------------
				Corrections
				----------------------------------------------------------------- */
				
				// silent_slide_show corrections
				
				if ( model.meta_dict.silent_slide_show === 'true' ){
					
					for ( i = 0; i < model.slide_array.length ; i++ ) {
						model.slide_array[i].timing = model.meta_dict.seconds_per_image * 1000 * i;
					}
					
				}
				
				trace(model.meta_dict);
				
				/* -----------------------------------------------------------------
				After loaded, call post parse
				----------------------------------------------------------------- */
				
				post_parse();
			}
		});
	};
	
	post_parse = function () {
		
		var caption, html, credit, i;
		
		
		/* -----------------------------------------------------------------
		Is it custom or standard?
		----------------------------------------------------------------- */
		
		if ( model.meta_dict.custom_size === 'true' ){
			model.path_to_images = model.path + 'custom';
		} else {
			model.path_to_images = model.path + '600_450';
			model.meta_dict.custom_width = 600;
			model.meta_dict.custom_height = 450;
		}
		
		/* -----------------------------------------------------------------
		Has image path been overridden?
		----------------------------------------------------------------- */
		
		if ( model.image_path_override ){
			model.path_to_images = model.image_path_override;
		}
		
		
		/* -----------------------------------------------------------------
		Set slide width and height
		----------------------------------------------------------------- */
		
		model.slide_width = Number( model.meta_dict.custom_width );
		model.slide_height = Number( model.meta_dict.custom_height );
		
		if ( init_object.width !== undefined ){
			model.slide_width = Number ( init_object.width );
		}
		
		if ( init_object.height !== undefined ){
			model.slide_height = Number ( init_object.height - model.controls_height );
		}
		
		/* -----------------------------------------------------------------
		The width and height vars are largely for reference. 
		----------------------------------------------------------------- */
		
		
		model.width = model.slide_width;
		model.height = model.slide_height + model.controls_height;
		
		
		/* -----------------------------------------------------------------
		Slide show type
		----------------------------------------------------------------- */
		
		
		if ( model.meta_dict.silent_slide_show === 'true' ){
			model.slideshow_type = 'silent';
		} else if ( model.meta_dict.slide_only === 'true' ){
			model.slideshow_type = 'click';
		} else {
			model.slideshow_type = 'audio';
		}
		
		
		/* -----------------------------------------------------------------
		XML loaded and dimensions set, let's draw it out.
		----------------------------------------------------------------- */
		
		
		create_initial_elements();
		
		/* -----------------------------------------------------------------
		Add the slide divs to the page (though do not add images yet)
		----------------------------------------------------------------- */
		
		
		credit = model.meta_dict.credits;
		credit = sanitize_string( credit ); // remove script tags
		
		html = '';
		
		for ( i = 0; i < model.slide_array.length; i++ ) {
			
			caption = model.slide_array[i].caption;
			caption = sanitize_string( caption ); // remove script tags
			
			html += '<div class = "slide"><div class="caption"><div class="caption_foreground_text">' + caption +'</div><div class="caption_background_text">' + caption +'</div></div><div class="credit"><div class="caption_foreground_text">' + credit +'</div><div class="caption_background_text">' + credit +'</div></div></div>';
			
		}
		
		$('#' + model.container_div + ' #slide_area').append( html );
		
		//
		  
		
		image_update();
		
		format_display();

		counter_update();
		caption_update();
		
	};
	
	create_initial_elements = function () {
		
		var container, audio_template, silent_template, click_template;
		
		container = model.container_div;
		
		/* -----------------------------------------------------------------
		Initial size and css position type
		----------------------------------------------------------------- */
		
		// div must be position relative or absolute
		if ( $( '#' + container ).css('position')  === 'static' ){
			$( '#' + container ).css({'position': 'relative'});
		}
		
		$( '#' + container ).css({'height': ( model.slide_height + model.controls_height ), 'width': ( Number ( model.slide_width ) ) });
		
		/* -----------------------------------------------------------------
		----------------------------------------------------------------- */
		
		// is it a click or silent play
		
		trace("model.meta_dict.silent_slide_show: " + model.meta_dict.silent_slide_show);
		
		audio_template = "<div id='background'></div><div id='slide_area'></div><div id='controls'><div id='controls_left'><ul id='nav'> <li id='play'><a href='#' id='play'>Play</a></li> <li id='stop'><a href='#' id='stop'>Stop</a></li> <li id='pause'><a href='#' id='pause'>Pause</a></li> <li id='resume'><a href='#' id='resume'>Resume</a></li> <li id='back'><a href='#' id='back'>Back</a></li> <li id='next'><a href='#' id='next'>Next</a></li><li id='counter'><span id='counter'></span></li> <li id='caption'><a href='#' id='caption'>Caption</a></li> <li id='credits'><a href='#' id='credits'>Credits</a></li></ul></div><div id='audio'></div></div>";
		
		silent_template = "<div id='background'></div><div id='slide_area'></div><div id='controls'><div id='controls_left'><ul id='nav'> <li id='play'><a href='#' id='play'>Play</a></li> <li id='stop'><a href='#' id='stop'>Stop</a></li> <li id='pause'><a href='#' id='pause'>Pause</a></li> <li id='resume'><a href='#' id='resume'>Resume</a></li> <li id='back'><a href='#' id='back'>Back</a></li> <li id='next'><a href='#' id='next'>Next</a></li><li id='counter'><span id='counter'></span></li> <li id='caption'><a href='#' id='caption'>Caption</a></li> <li id='credits'><a href='#' id='credits'>Credits</a></li></ul></div></div>";
		
		click_template = "<div id='background'></div><div id='slide_area'></div><div id='controls'><div id='controls_left'><ul id='nav'> <li id='resume'><a href='#' id='resume'>Resume</a></li> <li id='back'><a href='#' id='back'>Back</a></li> <li id='next'><a href='#' id='next'>Next</a></li><li id='counter'><span id='counter'></span></li> <li id='caption'><a href='#' id='caption'>Caption</a></li> <li id='credits'><a href='#' id='credits'>Credits</a></li></ul></div></div>";
		
		if ( model.slideshow_type === 'silent' ){
			
			$( '#' + container ).prepend( silent_template );
			
		} else if ( model.slideshow_type === 'click' ){
			
			$( '#' + container ).prepend( click_template );
		
		} else if ( model.slideshow_type === 'audio' ){
			
			$( '#' + container ).prepend( audio_template );
			
			load_audio();
			
			
		}
		
		$( '#' + container ).prepend("<div id='lowerthirds'></div>");
		
		/* -----------------------------------------------------------------
		Apply the proper CSS class for the controls
		----------------------------------------------------------------- */
		
		if ( model.nav_style === 'iPad'){
			$( '#' + container ).addClass( 'iDevices' );
		}
		
		/* -----------------------------------------------------------------
		Adjust next/back for click through slide shows
		----------------------------------------------------------------- */
		
		if ( model.slideshow_type === 'click' ){
			$( '#' + container + ' a#back').css({'left':'0px'});
			$( '#' + container + ' a#next').css({'left':'62px'});
			$( '#' + container + ' li#counter').css({'left':'133px'});
			
		}
		
		
		/* -----------------------------------------------------------------
		Buttons, clicks and hovers
		----------------------------------------------------------------- */
		
		
		$( '#' + container + ' #slide_area').click( function ( event ) {

			if ( model.current_slide < $( '#' + container + ' .slide').length - 1 ){
				change_slide( model.current_slide + 1 );
			}
			
			event.preventDefault();
			

		});
		
		
		$( '#' + container + ' a#stop').click( function ( event ) {
			change_state('stop');
			event.preventDefault();
		});
		
		$( '#' + container + ' a#play').click( function ( event ) {
			
			if ( model.state === 'stop' ){
				// start playing
				change_state('play');
			} else if ( model.state === 'pause' ){
				// start playing
				change_state('play');
			} else if ( model.state === 'play' ){
				// pause
				change_state('pause');
			}
			
			event.preventDefault();
			
		});
		
		$( '#' + container + ' a#pause').click( function ( event ) {
			
			if ( model.state === 'stop' ){
				// start playing
				change_state('play');
			} else if ( model.state === 'pause' ){
				// start playing
				change_state('play');
			} else if ( model.state === 'play' ){
				// pause
				change_state('pause');
			}
			
			event.preventDefault();
			
		});
		
		$( '#' + container + ' a#resume').click( function ( event ) {
			
			if ( model.state === 'stop' ){
				// start playing
				change_state('play');
			} else if ( model.state === 'pause' ){
				// start playing
				change_state('play');
			} else if ( model.state === 'play' ){
				// pause
				change_state('pause');
			}
			
			event.preventDefault();
			
		});
		


		$( '#' + container + ' a#next').click( function ( event ) {

			if ( model.current_slide < $( '#' + container + ' .slide').length - 1 ){
				change_slide( model.current_slide + 1 );
			}

			event.preventDefault();

		});

		$( '#' + container + ' a#back').click( function ( event ) {

			if ( model.current_slide > 0 ){
				change_slide ( model.current_slide - 1 );
			}
			event.preventDefault();

		});

		$( '#' + container + ' a#caption').click( function ( event ) {
			model.credit_displayed = false;
			model.caption_displayed = ! model.caption_displayed;
			caption_update();
			event.preventDefault();

		});

		$( '#' + container + ' a#credits').click( function ( event ) {

			model.credit_displayed = ! model.credit_displayed;
			model.caption_displayed = false;
			caption_update();

			event.preventDefault();

		});
		
		
		
	};
	
	time_check = function (){
				
		model.playhead_elapsed_ms += 50;
		
		trace("timer: " + model.playhead_elapsed_ms );
		
		check_for_active_image( model.playhead_elapsed_ms );
		check_for_lower_third_event();
		
	};
	
	check_for_active_image = function () {
		
		var active_image, i;
		
		active_image = 0;
		
		for ( i = 0; i < model.slide_array.length; i ++ ){
			if ( model.slide_array[ i ].timing < model.playhead_elapsed_ms ){
				active_image = i;
			}else{
				break;
			}
		}
		
		if ( active_image !== model.current_slide ){
			change_slide ( active_image );
		}
		
	};
	
	check_for_lower_third_event = function () {
		
		var active_lowerthird, i, inpoint, outpoint, playhead_position;
		
		active_lowerthird = -1;
		
		for ( i = 0; i < model.lowerthirds_array.length; i ++ ){
			inpoint = model.lowerthirds_array[i].inpoint * 1000;
			outpoint = ( model.lowerthirds_array[i].inpoint + model.lowerthirds_array[i].duration ) * 1000;
			playhead_position = model.playhead_elapsed_ms;
			if ( playhead_position >= inpoint && playhead_position <= outpoint ) {
				active_lowerthird = i;
				break;
			}
		}
		
		if ( active_lowerthird != model.current_lowerthird ){
			// new Lowerthird event (could be the start or end of a LT)
			model.current_lowerthird = active_lowerthird;
			change_lowerthird();		
		}
		
	};
	
	change_lowerthird = function (){
		
		var name, title, lowerthird_div;
		
		lowerthird_div = $( '#' + model.container_div + ' #lowerthirds') ;
		
		if ( model.current_lowerthird !== -1 ){
			// show lowerthird
			trace('show lowerthird');
			
			name = model.lowerthirds_array[ model.current_lowerthird ].name;
			title = model.lowerthirds_array[ model.current_lowerthird ].title;
			
			name = sanitize_string( name );
			title = sanitize_string( title );
			
			lowerthird_div.html( '<p class="lt_name">' + name + '</p><p class="lt_title">' + title + '</p>' );
			
			lowerthird_div.css( { 'top': ( model.slide_height - lowerthird_div.height() ) } );
			
			
			lowerthird_div.fadeIn(300);
			
		} else {
			// hide lowerthird
			trace('hide lowerthird');
			lowerthird_div.fadeOut(300);
		}
		
	};
	
	sanitize_string = function ( str ){
		
		return str.replace(/<script[^>]*?>[\s\S]*?<\/script>/gi, ''); // removes <script> tags
		
		// TODO: find a better regex that only allows safe tags to pass
		// specifically, we need to strip out img tags
		
	};
	
	load_audio = function (){
		
		trace('load_audio');
		
		var container, total_time;
		
		
		container = model.container_div;
				
		$( '#' + container	+ " #audio").jPlayer( {
			customCssIds: true,
			oggSupport: true,
			ready: function () {
				this.element.jPlayer("setFile", model.path_to_audio + "audio_hi.mp3", model.path_to_audio + "audio_hi.ogg").jPlayer('play').jPlayer('pause');
			}
		});
		
		$('#' + container  + " #audio").jPlayer("onProgressChange", function(lp,ppr,ppa,pt,tt) {
				
				model.playhead_load_percent = Math.floor(lp);
				
				/* -----------------------------------------------------------------
				Correct for total time.	 tt is only reported correctly after all
				audio has loaded, so we'll use the duration variable that's stored
				with the slide show's XML.
				----------------------------------------------------------------- */
				
				total_time = Number ( model.meta_dict.duration );
				
				if ( pt === undefined ) {
					pt = 0;
				}
				
				model.playhead_remaining_ms = Math.floor(total_time - pt);
				model.playhead_elapsed_ms = Math.floor(pt);
				
				counter_update();
				if ( model.state === 'play'){
					check_for_active_image();
				}
				check_for_lower_third_event();
			
		});
		
		
		
	};

	change_state = function ( state ){
		
		var container;
		
		model.state = state;
		container = model.container_div;
		
		
		if ( model.state === 'play'){
			
			$('#' + container + ' a#play').html( 'pause' );
			
			$('#' + container + ' #nav li#play a').hide();
			$('#' + container + ' #nav li#stop a').show();
			$('#' + container + ' #nav li#pause a').show();
			$('#' + container + ' #nav li#resume a').hide();
			
			if ( model.slideshow_type === 'audio'){

				$('#' + container + ' #audio').jPlayer('play');

				trace('start audio');

			} else {

				clearInterval( model.time_interval );

				model.time_interval = setInterval(function(){

					time_check();

				}, 50);

			}
			
		} else if ( model.state === 'pause' ){
			
			
			$('#' + container + ' #nav li#play a').hide();
			$('#' + container + ' #nav li#stop a').show();
			$('#' + container + ' #nav li#pause a').hide();
			$('#' + container + ' #nav li#resume a').show();
			
			
			$('#' + container + ' a#play').html( 'play' );
			
			clearInterval( model.time_interval );
			
			$('#' + container + ' #audio').jPlayer('pause');
			
			
		} else if ( model.state === 'stop' ){
			
			$('#' + container + ' #nav li#play a').show();
			$('#' + container + ' #nav li#stop a').hide();
			$('#' + container + ' #nav li#pause a').hide();
			$('#' + container + ' #nav li#resume a').hide();
			
			
			$('#' + container + ' a#play').html( 'play' );
			
			clearInterval( model.time_interval );
			
			$('#' + container + ' #audio').jPlayer('stop');
			
			
		}
		
		
		
	};
	
	image_update = function () {
		
		var i, filename, slide;
		
		/* -----------------------------------------------------------------
		Check for images to add
		----------------------------------------------------------------- */
		
		if ( ( model.current_slide + model.preload_limit ) > model.images_loaded && model.images_loaded < model.slide_array.length ){
			trace('we need more images');

			i = model.images_loaded;

			trace('loading #' + i);


			filename = model.slide_array[i].filename;

			trace('filename: ' + filename);
			
			
			$( '#' + model.container_div + ' .slide:eq(' + i + ')').prepend('<div class="image"><img src="' + model.path_to_images + '/' + filename + '" alt="image" /></div>');
							
			// Set the load callback
			$( '#' + model.container_div + ' .slide:eq(' + i + ') img').load( function(){
				
				if ( i === 0 ){
					
					slide = $( '#' + model.container_div + ' .slide:first');
					
					slide.css({'opacity':'0'});
					slide.show();
					center_and_size_slide(0);
					slide.css({'opacity':'1'});
				}
				
				trace('image #' + i + ' loaded.');
				
			});

			model.images_loaded = ( Number( i ) + 1 );
			image_update();



		}else{
			trace('all buffered');
		}
	};
	
	format_display = function (){
		
		var caption_credit_css;
		
		/* -----------------------------------------------------------------
		Initial credits and captions
		----------------------------------------------------------------- */

		if ( ! model.caption_displayed ){
			$('#' + model.container_div + ' .caption' ).css('display', 'none');
		}

		if ( ! model.credit_displayed ){
			$('#' + model.container_div + ' .credit' ).css('display', 'none');
		}
		
		/* -----------------------------------------------------------------
		Hide lowerthirds
		----------------------------------------------------------------- */
		
		$('#' + model.container_div + ' #lowerthirds' ).css('display', 'none');
		
		/* -----------------------------------------------------------------
		Hide all slides
		----------------------------------------------------------------- */

		$('#' + model.container_div + ' .slide').css('display', 'none');

		/* -----------------------------------------------------------------
		Individual slide CSS
		----------------------------------------------------------------- */

		$( '#' + model.container_div + ' .slide' ).css({'width': model.slide_width + 'px', 'height': model.slide_height + 'px'});
		
		caption_credit_css = {'color': 'white', 'font-family': 'Verdana', 'font-size': '11px', 'width': model.slide_width  + 'px'};
		
		if ( model.nav_style === 'iPad' ){
			caption_credit_css = {'color': 'white', 'font-family': 'Verdana', 'font-size': '18px', 'width': model.slide_width  + 'px'};
		}
		
		
		$( '#' + model.container_div + ' .credit' ).css( caption_credit_css );
		$( '#' + model.container_div + ' .caption' ).css( caption_credit_css);
		
		$( '#' + model.container_div + ' .caption_foreground_text' ).css({'padding': '5px'});
		$( '#' + model.container_div + ' .caption_background_text' ).css({'position':'absolute', 'top':'0px', 'background': '#000000', 'width': ( model.slide_width	 - 10) + 'px', 'opacity': '0.5', 'padding': '5px'});
		
		
		/* -----------------------------------------------------------------
		Display specific CSS
		----------------------------------------------------------------- */

		$( '#' + model.container_div + ' #background').css({'background':'#000000', 'z-index': '-1', 'width': model.slide_width + 'px', 'height': model.slide_height + 'px'});
		
		$( '#' + model.container_div + ' #image_area').css({'width': model.slide_width + 'px', 'height': model.slide_height + 'px'});
		
		// extra hairline is caused by the top attr in the next line!!!!!!
		
		$( '#' + model.container_div + ' #controls').css({'top': model.slide_height + 'px', 'background': '#' + model.meta_dict.controls_hex, 'height': model.controls_height + 'px', 'width': model.slide_width + 'px', 'font-size': '5px'});
		
		/* -----------------------------------------------------------------
		Position x position of buttons
		----------------------------------------------------------------- */
		
		var credits_button = $( '#' + model.container_div + ' #controls li#credits a');
		credits_button.css({'left': model.width - credits_button.width() });
		
		var caption_button = $( '#' + model.container_div + ' #controls li#caption a');
		caption_button.css({'left': model.width - credits_button.width() - caption_button.width() -1 });
		
		/* -----------------------------------------------------------------
		----------------------------------------------------------------- */
		
		
		
		 
	};
	
	counter_update = function (){
		
		var counter, converted_time;
		
		counter = $( '#' + model.container_div + ' #counter');
		
		if ( model.slideshow_type === 'audio'){
			
			if ( model.playhead_remaining_ms === undefined ){
				model.playhead_remaining_ms = Number ( model.meta_dict.duration );
			}
			
			converted_time = $.jPlayer.convertTime( model.playhead_remaining_ms );
			
			if ( converted_time !== counter.html() ){
				counter.html( converted_time );
			}
			
		} else {
			counter.html( ( model.current_slide + 1 ) + '/' + model.slide_array.length );
		}
		
		
	};
	
	caption_update = function () {
		
		if ( model.caption_displayed ){

			$( '#' + model.container_div + ' .slide:eq(' + model.current_slide + ')').children('.caption').stop().slideDown(200);
			$( '#' + model.container_div + ' a#caption_button').html("hide captions");

		} else {
			$( '#' + model.container_div + ' .slide:eq(' + model.current_slide + ')').children('.caption').stop().slideUp(200);
			$( '#' + model.container_div + ' a#caption_button').html("captions");
		}

		if ( model.credit_displayed ){
			$( '#' + model.container_div + ' .slide:eq(' + model.current_slide + ')').children('.credit').stop().slideDown(200);
			$( '#' + model.container_div + ' a#credit_button').html("hide credits");
		}else{
			$( '#' + model.container_div + ' .slide:eq(' + model.current_slide + ')').children('.credit').stop().slideUp(200);
			$( '#' + model.container_div + ' a#credit_button').html("credits");
		}
	};
	
	change_slide = function ( slide_number ) {
		
		var transition_speed; 
		
		trace ("---> change_slide()");
		trace ("removing slide: " + model.current_slide );
		trace ("adding slide: " + slide_number );
		//trace ($( '#' + model.container_div + ' .slide:eq(' + slide_number + ')').html() );

		model.previous_slide = model.current_slide;
		
		transition_speed = 300;
		
		// hide existing image other slides
		
		$( '#' + model.container_div + ' .slide:eq(' + model.current_slide + ')').fadeOut( transition_speed );
		
		// save new slide number
		model.current_slide = slide_number;
		
		//fade out background slide
		
		
		// display new slide, then call post_change_slide
		$( '#' + model.container_div + ' .slide:eq(' + slide_number + ')').fadeIn( transition_speed, function () {
			//hide previous image
			$( '#' + model.container_div + ' .slide:eq(' + model.previous_slide + ')').hide();
			image_update();
			
			
		} );

		center_and_size_slide( slide_number );

		caption_update();
		counter_update();
		
		// update the playhead_elapsed_ms to the proper setting if not playing
		if ( model.state !== 'play') {
			model.playhead_elapsed_ms = model.slide_array[ slide_number ].timing;
		}
		
		
		
	};
	
	center_and_size_slide = function ( slide_number ) {
		
		
		/* -----------------------------------------------------------------
		Measure, size and position the images
		Perhaps this could be done when the image loads
		----------------------------------------------------------------- */
		
		var slide, image_width, image_height, need_adjustment, new_image_width, 
		new_image_height;
		
		slide = $( '#' + model.container_div + ' .slide:eq(' + slide_number + ') img');
		image_width = slide.width();
		image_height = slide.height();
		
		need_adjustment = false;
		
		// check to see if slide needs to be scaled down
		if ( image_width > model.slide_width || image_height > model.slide_height ){
			need_adjustment = true;
		}
		
		// check to see if slide show needs to be scaled up
		if ( ( image_height !== model.slide_height || image_width !== model.slide_width ) && model.upscaling === true ){
			need_adjustment = true;
		}
		
		if ( need_adjustment ){
			
			// do the width
			
			new_image_width = model.slide_width;
			new_image_height = image_height / ( image_width / model.slide_width );
			
			image_width = new_image_width;
			image_height = new_image_height;
			
			// check to see if new height is too big, if so, make smaller
			
			if ( image_height > model.slide_height ){

				new_image_height = model.slide_height;
				new_image_width = image_width / ( image_height / model.slide_height );
				
				image_width = new_image_width;
				image_height = new_image_height;

			}
			
			slide.css( {'width': new_image_width, 'height': new_image_height } );
			
		}
		
		trace("image_width: " + image_width);
		trace("image_height: " + image_height);

		slide.css( { 'top': ( model.slide_height - image_height ) / 2, 'left': ( model.slide_width - image_width ) / 2 } );
		
	};
	
	change_size = function ( w, h ){
		
		trace('change_size: ' + w + 'x' + h);
		
		model.width = w;
		model.height = h;
		
		model.slide_height = model.height - model.controls_height;
		model.slide_width = model.width;
		
		format_display();
		$( '#' + model.container_div + ' .slide:eq(' + model.current_slide + ')').show();
		center_and_size_slide( model.current_slide );
		
	};
	
	trace = function ( msg ) {
		
		if ( model.debug ) {
			console.log( msg );
		}
	};
	
	load_and_parse_xml();
	
	/* -----------------------------------------------------------------
	Public items are returned here!
	
	Inspired the "revealing" version of the module pattern:
	http://www.wait-till-i.com/2007/08/22/again-with-the-module-pattern-reveal-something-to-the-world/
	----------------------------------------------------------------- */
	
	return {
		model: model,
		change_size: change_size
	};
	
	/* -----------------------------------------------------------------
	----------------------------------------------------------------- */
	

};
	
		


