function isImageOk(img) {
    // During the onload event, IE correctly identifies any images
    // that weren't downloaded as not complete. Others should too.
    // Gecko-based browsers act like NS4 in that they report this
    // incorrectly: they always return true.
    if (!img.complete) {
        return false;
    }

    // However, they do have two very useful properties: naturalWidth
    // and naturalHeight. These give the true size of the image. If
    // it failed to load, either of these should be zero.
    if (typeof img.naturalWidth != "undefined" && img.naturalWidth == 0) {
        return false;
    }

    // No other way of checking: assume it's ok.
    return true;
}

function reflow(target) {
	// Make sure IE correctly sizes scaled images
	if (target.constructor == Array) {
		// Array
		for (var i in target) {
			reflow(target[i]);
		}
	} else {
		// DOM Node
		target.style.border = target.style.border;
	}
}



var DynamicStreamPlayer = function(config) {

	var pub = new Object();
	var flashVersion = "9.0.0";
	var installHtml = "<li class='flash-info'><a href='http://www.adobe.com/go/getflashplayer'>Install the latest Adobe Flash plugin to watch this video.</a></li>"

	var jqContainer = $(config.containerElement);
	var jqVideoContainer = jqContainer.find('.video');
	var jqControlsContainer = jqContainer.find('.control-bar');
	var jqCoverImage = jqContainer.find('img');
	var jqInstallHtmlLocation = $(config.installHtmlLocation);
	
	if (config.debug) {
		var jqDebugContainer = $("<div class='debug'></div>");
		$(document.body).append(jqDebugContainer);
	}


	pub.embed = function() {
		pub.debug("embedding");
		
		if (swfobject.hasFlashPlayerVersion(flashVersion)) {
			jqVideoContainer.prepend("<div id='videoflash'></div>");

			function coverImageLoaded() {
				
				// Force redraw so IE gets the right image dimensions
				reflow(jqCoverImage[0]);

				var flashvars = {
					initFunction: config.namespace+".init",
					playingFunction: config.namespace+".statusPlaying",
					pausedFunction: config.namespace+".statusPaused",
					stoppedFunction: config.namespace+".statusStopped",
					completeFunction: config.namespace+".statusComplete",
					timeFunction: config.namespace+".position",
					volstepFunction: config.namespace+".volstep",
					debugFunction: config.namespace+".debug",

					streamListJson: config.streamListJson,
					bwcheckServer: config.bwcheckServer,
					videoServer: config.videoServer,
					videoWidth: jqCoverImage[0].width,
					videoHeight: jqCoverImage[0].height,
					volsteps: config.volsteps
				};
				var params = {
					wmode: "transparent"
				};
				var attributes  = {};
				
				// Embed Flash with swfobject
				swfobject.embedSWF(config.swfUrl, "videoflash", 1, 1, flashVersion, "", flashvars, params, attributes);				
			}

			// Have to wait for image to load otherwise webkit reports the wrong width
			if (isImageOk(jqCoverImage[0])) {
				coverImageLoaded();
			} else {
				jqCoverImage.load(coverImageLoaded);
			}
		} else {
			jqInstallHtmlLocation.append($(installHtml));
		}
	}


	// ControlButton class
	function ControlButton(buttonLabel, buttonAction, containerElem) {
		var jqLabelElem = $("<span>"+buttonLabel+"</span>");
		var jqEnabledElem = $("<a href='#'></a>");
		var jqDisabledElem = $("<strong></strong>");
		var jqContainerElem = $(containerElem);		
		var currentElem;
		
		var enable = function() {
			jqDisabledElem.remove();
			jqEnabledElem.append(jqLabelElem);
			jqContainerElem.append(jqEnabledElem);
			jqEnabledElem.click(buttonAction);
			currentElem = jqEnabledElem[0];
		}

		var disable = function() {
			jqEnabledElem.remove();
			jqDisabledElem.append(jqLabelElem);
			jqContainerElem.append(jqDisabledElem);
			currentElem = jqDisabledElem[0];			
		}

		var setLabel = function(newLabel) {
			if (newLabel) {
				jqLabelElem.text(newLabel);
			} else {
				jqLabelElem.text(buttonLabel);
			}
		}

		disable();

		return({
			'element': currentElem,
			'enable': enable,
			'disable': disable,
			'setLabel': setLabel,
			'linkElem': jqEnabledElem[0]
		});
	}

	var initReal = function() {
		pub.debug("creating interface");
		
		// Setup Controls
		jqControlsContainer.empty();
		var jqControlsList = $("<ul class='controls'></ul>");
		jqControlsContainer.append(jqControlsList)

		// Replace script preference
//		setScriptPrefrence();

		// Create buttons
		var jqPlayButtonContainer = $("<li class='play'></li>");
		playButton = new ControlButton("Play", playVideo, jqPlayButtonContainer[0]);
		var jqPauseButtonContainer = $("<li class='pause'></li>");
		pauseButton = new ControlButton("Pause", pauseVideo, jqPauseButtonContainer[0]);
		var jqStopButtonContainer = $("<li class='stop'></li>");
		stopButton = new ControlButton("Stop", stopVideo, jqStopButtonContainer[0]);

		// Add buttons
		jqControlsList.append(jqPlayButtonContainer);
		jqControlsList.append(jqPauseButtonContainer);
		jqControlsList.append(jqStopButtonContainer);

		// Setup cover image
		jqCoverContainer = $("<div class='cover'></div>");
		coverImageButton = new ControlButton("Play", playVideo, jqCoverContainer[0]);
		jqCoverContainer.prepend(jqCoverImage);
		jqVideoContainer.append(jqCoverContainer);

		// Add Pos bar		
		jqProgressBarContainer = $("<div class='progress-bar-container'></div>")
		jqControlsContainer.append(jqProgressBarContainer)

		function setPositionListener(evt) {
			progBar.setPlayed(evt);
			seekVideo(evt)
		}

		progBar = new ProgressBar(setPositionListener);
		jqProgressBarContainer.append(progBar.element);

		jqContainer.bind("mouseenter", mouseEnteredVideo);
		jqContainer.bind("mouseout", mouseLeftVideo);
		$(document).bind("mouseout", mouseLeftHTML);

		$(coverImageButton.linkElem).bind("focus", keyboardEnteredVideo);
		$(playButton.linkElem).bind("focus", keyboardEnteredVideo);
		$(pauseButton.linkElem).bind("focus", keyboardEnteredVideo);
		$(stopButton.linkElem).bind("focus", keyboardEnteredVideo);
		$(coverImageButton.linkElem).bind("blur", keyboardLeftVideo);
		$(playButton.linkElem).bind("blur", keyboardLeftVideo);
		$(pauseButton.linkElem).bind("blur", keyboardLeftVideo);
		$(stopButton.linkElem).bind("blur", keyboardLeftVideo);

		jqContainer.addClass('active');
	}

	// Started from Flash
	pub.init = function() {
		// Avoid FireFox crash by taking the methods away from the Flash function call
		var t = setTimeout(function(){ initReal(); }, 1);
	}



	// Mouse/Keyboard events that control the visibility of the controls

	function hideControls() {
		jqControlsContainer.addClass('rm');
	}

	function showControls() {
		jqControlsContainer.removeClass('rm');
	}


	function mouseEnteredVideo(evt) {
		showControls();
	}
	function mouseLeftVideo(evt) {
		// Get the element the mouse moved to (mouseover)
		var movedTo = (evt.relatedTarget) ? evt.relatedTarget : evt.toElement;

		if (!movedTo) {return}
		
		while (movedTo != jqContainer[0] && movedTo.nodeName != 'BODY') {
			movedTo = movedTo.parentNode;
			if (movedTo == jqContainer[0] | !movedTo) return;
		}
		
		hideControls();
	}
	function mouseLeftHTML(evt) {
		// Get the element the mouse moved to (mouseover)
		var movedTo = (evt.relatedTarget) ? evt.relatedTarget : evt.toElement;

		if (!movedTo || movedTo.nodeName == "HTML") {
			// Mouse moved out of document (no movedTo)
			hideControls();
		}
	}
	function keyboardEnteredVideo(evt) {
		showControls();
	}
	function keyboardLeftVideo(evt) {
		hideControls();
	}



	// Public methods for Flash

	pub.statusPlaying = function() {
		pub.debug("statusPlaying");		
		
		playButton.disable();
		pauseButton.enable();
		$(pauseButton.linkElem).bind("focus", keyboardEnteredVideo);
		$(pauseButton.linkElem).bind("blur", keyboardLeftVideo);
		stopButton.enable();
		$(stopButton.linkElem).bind("focus", keyboardEnteredVideo);
		$(stopButton.linkElem).bind("blur", keyboardLeftVideo);
		
		coverImageButton.disable();
		jqCoverContainer.addClass("hidden");
		
		pub.eventPlaying();
	}

	pub.statusPaused = function() {
		pub.debug("statusPaused");				
		
		playButton.enable();
		$(playButton.linkElem).bind("focus", keyboardEnteredVideo);
		$(playButton.linkElem).bind("blur", keyboardLeftVideo);
		pauseButton.disable();
		stopButton.enable();		
		$(stopButton.linkElem).bind("focus", keyboardEnteredVideo);
		$(stopButton.linkElem).bind("blur", keyboardLeftVideo);
		
		pub.eventPaused();		
	}

	pub.statusStopped = function() {
		pub.debug("statusStopped");						
		
		playButton.enable();
		$(playButton.linkElem).bind("focus", keyboardEnteredVideo);
		$(playButton.linkElem).bind("blur", keyboardLeftVideo);
		pauseButton.disable();
		stopButton.disable();
		
		coverImageButton.setLabel();		
		jqCoverImage.removeClass("rm");
		
		coverImageButton.enable();		
		jqCoverContainer.removeClass("hidden");	
		$(coverImageButton.linkElem).bind("focus", keyboardEnteredVideo);
		$(coverImageButton.linkElem).bind("blur", keyboardLeftVideo);
		
		pub.eventStopped();			
	}
	
	pub.statusComplete = function() {
		pub.debug("statusComplete");			
		
		playButton.enable();
		$(playButton.linkElem).bind("focus", keyboardEnteredVideo);
		$(playButton.linkElem).bind("blur", keyboardLeftVideo);
		pauseButton.disable();
		stopButton.disable();
		
		coverImageButton.setLabel("replay");
		jqCoverImage.addClass("rm");
		
		coverImageButton.enable();		
		jqCoverContainer.removeClass("hidden");		
		$(coverImageButton.linkElem).bind("focus", keyboardEnteredVideo);
		$(coverImageButton.linkElem).bind("blur", keyboardLeftVideo);
		
		pub.eventComplete();			
	}	

	pub.position = function(pos, dur) {
		//console.log( (pos/dur)*100 );
		progBar.setPlayed(pos/dur);
		if (!progBar.enabled) {
			progBar.enable();		
		}
	}
	
	pub.debug = function(message) {
		if (config.debug) {
			jqDebugContainer.prepend("<p>"+message+"</p>");
		}
	}

	// Animation Control from HTML/JS
	function playVideo() {document.getElementById("videoflash").playVideo(); return false}
	function pauseVideo() {document.getElementById("videoflash").pauseVideo(); return false}
	function stopVideo() {document.getElementById("videoflash").stopVideo(); return false}
	function seekVideo(pos) {document.getElementById("videoflash").seekVideo(pos); return false}



	// Events
	pub.eventPlaying = function() {}
	pub.eventPaused = function() {}
	pub.eventStopped = function() {}
	pub.eventComplete = function() {}	


	// Return public methods and variables
	return pub;
}
