// provides a controls for starting and stopping and navigating through a flash video
// to start: $('embed').flashcontrol()
// to stop: embed.destroyflash()
// notice the stop method is directly on the dom element and not through jquery.
// either getElementById('#embed).destroyflash(), $('embed').each(function() { this.destroyflash(); }), or something similar.
jQuery.fn.flashcontrol = function(options) {
	// set options
	var useroptions = {
		hidden : false
	}
	$.extend(useroptions, options);
	
	// create flashcontrol
	return this.each(function() {
		// constants
		var PROPERTY_CURRENT_FRAME = 4;
		var PROPERTY_TOTAL_FRAMES = 5;
		var PROPERTY_FRAMES_LOADED = 12;
		
		// setup variables
		var timelinemame = "/"; // change this if the timeline to be used is something other than "/" (main timeline)
		var updateratems = 250; // progress bar update rate
		if($.browser.msie)
			updateratems = 500; // IE can't keep up on slow PCs
		
		
		var controlheight = 25; // height of the flash controls and progress bar
		var controlsid = "flashcontrol_"+Math.floor(Math.random() * 100000);
		var startnow = true;
		var hidden = useroptions.hidden;
		var readywaittimeoutms = 5000; // amount of time to wait for the embed element become ready
	
		// status variables
		var totalframes = 0; 
		var loadedframes = 0;
		var currentframe = 0;
		var statusupdatetracker = 0; // used later to track the setInterval call so it can be stopped
		var finishedloading = false; // tracks whether loading is complete so the loading bar can stop being updated
		var isplaying = startnow;
		
		movieelement = this;
	
		var movieelementposition = $(movieelement).position();
		
		// construction
		$(movieelement).after("<div id='"+controlsid+"' class='flashcontrol'>"
					+"<div class='controls'>"+(startnow?"pause":"play")+"</div>"
					+"<div class='progressbar_shell'></div>"
					+"<div class='progressbar_fill_loaded'></div>"
					+"<div class='progressbar_fill_playback'></div>"
					+"</div>"
					);
		
		$('#'+controlsid).css({
			position: 'absolute',
			width: $(movieelement).width(),
			top: (movieelementposition.top + $(movieelement).height())+'px',
			left: movieelementposition.left+'px',
			height: controlheight+'px',
			display : (hidden ? 'none' : 'block')
		});
		
		$('#'+controlsid+' .controls').css({
			position: 'absolute',
			left: '0px',
			top: '0px',
			width: '50px',
			border: '1px solid #fff',
			height: controlheight+'px',
			color: '#fff',
			fontFamily: 'arial',
			fontSize: '12px',
			lineHeight: controlheight+'px',
			textAlign: 'center',
			cursor: 'pointer'
		});
		
		$('#'+controlsid+' .progressbar_fill_playback').css({
			position: 'absolute',
			left: ($('#'+controlsid+' .controls').width()+3)+'px',
			top: '0px',
			width: '1px',
			border: '1px solid #fff',
			backgroundColor: '#eee',
			height: controlheight+'px'
		});
		
		$('#'+controlsid+' .progressbar_fill_loaded').css({
			position: 'absolute',
			left: ($('#'+controlsid+' .controls').width()+3)+'px',
			top: '0px',
			width: '1px',
			border: '1px solid #fff',
			backgroundColor: '#aaa',
			opacity: '0.5',
			filter: 'alpha (opacity=50)',
			height: controlheight+'px'
		});
		
		$('#'+controlsid+' .progressbar_shell').css({
			position: 'absolute',
			left: ($('#'+controlsid+' .controls').width()+3)+'px',
			top: '0px',
			width: ($(movieelement).width() - $('#'+controlsid+' .controls').width()-5)+'px',
			border: '1px solid #fff',
			backgroundColor: '#000',
			opacity: '0.5',
			filter: 'alpha (opacity=50)',
			height: controlheight+'px'
		});
		
		if(startnow)
			_startPlayback();
		
		// events
		$('#'+controlsid+' .progressbar_shell, #'+controlsid+' .progressbar_fill_playback, #'+controlsid+' .progressbar_fill_loaded').click(function(event) {
			event.stopPropagation();
			var offset = $('#'+controlsid+' .progressbar_shell').offset();
			var position = (event.pageX - offset.left) / $('#'+controlsid+' .progressbar_shell').width();  
			
			_setCurrentPosition(position);
		});
		
		$('#'+controlsid+' .controls').click(function(event) {
			event.stopPropagation();
			
			if(isplaying)
				_stopPlayback();
			else
				_startPlayback();
		});
		
		$(window).resize(function() {
			$('#'+controlsid).css({
				width: $(movieelement).width(),
				top: (movieelementposition.top + $(movieelement).height())+'px',
				left: movieelementposition.left+'px'
			});
			
			$('#'+controlsid+' .progressbar_shell').css({
				width: ($(movieelement).width() - $('#'+controlsid+' .controls').width()-5)+'px'
			});
			
			_updatePlayProgressBar(updateratems);
			_updateLoadProgressBar(updateratems);
		});
		
		// progress update
		totalframes = _tryGetProperty(PROPERTY_TOTAL_FRAMES);
		
		statusupdatetracker = setInterval(function() {
			if(_isFinished(true))
				return;
			
			// set the frame
			loadedframes = _tryGetProperty(PROPERTY_FRAMES_LOADED);
			newcurrentframe = _tryGetProperty(PROPERTY_CURRENT_FRAME);
			if(typeof totalframes == 'undefined')
				totalframes = _tryGetProperty(PROPERTY_TOTAL_FRAMES);

			// if the video is stopped at the end, go through the stop procedure so the internal state will match
			if(newcurrentframe == totalframes)
				_stopPlayback();
			
			currentframe = newcurrentframe;
			
			// update totalframes if it's known to be incorrect
			if (currentframe > totalframes)
				totalframes = _tryGetProperty(PROPERTY_TOTAL_FRAMES);
			
			// update the progress bar
			_updatePlayProgressBar(updateratems);
			
			// only update loading until loading is complete.
			if(!finishedloading) {
				_updateLoadProgressBar(updateratems);
				if(loadedframes == totalframes)
					finishedloading = true;
			}
		}, updateratems);
		
		// utility functions
		function _setCurrentPosition(positionpercent) {
			var newframe = positionpercent * totalframes;
			movieelement.TGotoFrame("/", newframe);
			currentframe = newframe.toFixed(0);
			
			if(isplaying)
				_startPlayback(movieelement);
			
			_updatePlayProgressBar(0);
		}
		
		function _stopPlayback() {
			movieelement.TStopPlay("/");
			isplaying = false;
			$('#'+controlsid+' .controls').text('play');
			_updatePlayProgressBar(0);
		}
		
		function _startPlayback() {
			movieelement.TPlay("/");
			isplaying = true;
			$('#'+controlsid+' .controls').text('pause');
			_updatePlayProgressBar(0);
		}
		
		function _updatePlayProgressBar(animaterate) {
			var _curframe = currentframe;
			var _totframes = totalframes;
			var _shellwidth = $('#'+controlsid+' .progressbar_shell').width();
			var barwidth = 0;
			
			// make sure valid values are being used
			if(_totframes < 1)
				_totframes = 1
				
			if(_shellwidth < 1)
				_shellwidth = 1
			
			if(_curframe > 0) {
				barwidth = (_curframe / _totframes) * _shellwidth;
			}
			else {
				barwidth = 0;
			}
			
			$('#'+controlsid+' .progressbar_fill_playback').css({
				width : barwidth+'px'
			});
		}
		
		function _updateLoadProgressBar(animaterate) {
			var _curframe = loadedframes;
			var _totframes = totalframes;
			
			var _shellwidth = $('#'+controlsid+' .progressbar_shell').width();
			var barwidth = 0;
			
			// make sure valid values are being used
			if(_totframes < 1)
				_totframes = 1
				
			if(_shellwidth < 1)
				_shellwidth = 1
			
			if(_curframe > 0) {
				barwidth = (_curframe / _totframes) * _shellwidth;
			}
			else {
				barwidth = 0;
			}
			
			$('#'+controlsid+' .progressbar_fill_loaded').css({
				width : barwidth+'px'
			});
		}
		
		function _isFinished(cleanupiffinished) {
			if(typeof movieelement.TGetProperty == 'undefined') {
				if(cleanupiffinished)
					_cleanup();
				return true;
			}
			return false;
		}
		
		function _tryGetProperty(property) {
			value = 1; // one is a safe value to avoid divide by 0 errors that can happen
			try {
				value = movieelement.TGetProperty("/", property);
			}
			catch (e) {
				
			}
			return value;
		}
		
		function _cleanup() {
			clearInterval(statusupdatetracker);
			$('#'+controlsid).empty().remove();
		}
		
		// method attached to the movie
		movieelement.destroyflash = function () {
			_stopPlayback();
			_cleanup();
		}
	});
};

