/*
	WebcastPlayerClass
	last modified 2009-08-07
	Dependencies: BrowserClass.js, ExpandableCode.js, MediaPlayerManager_class.js, MultipleStateButton_class.js
*/
function WebcastPlayerClass(eventLogCallBack) {

		// querystring commands
		var COMPACT1_CMD = "compact=1";
		var COMPACT2_CMD = "compact=2";
		var COMPACT3_CMD = "compact=3";
		var OPTIONS_OFF_CMD = "options=0";
		var OPTIONS_ON_CMD = "options=1";
		var OPTIONS_HIDE_CMD = "options=2";
		var SEGMENT_CMD = "segment=";
		var VOLUME_CMD = "volume=";
		
		// private constants
		var MEDIA_LOG_RECORDER = "pages/actions/save_media_log.aspx";
		var MEDIA_ID_KEY = "mid";
		var LOG_TIMER_INTERVAL = 20000;
		var NETWORK_REQ_MESSAGE = "Note: you must have an active connection to the network to access this feature. Do you wish to proceed?";
		var VOLUME_OFFSET_LEFT = 10;
		var VOLUME_OFFSET_RIGHT = 25;
		var PODCAST_EXTENSIONS = [ ".mp3", ".aac", ".kpg" ];

		// flags
		this.isAudioOnly = false;
		this.isKontiki = false;
		this.isDownloadable = false;
		this.isTelephone = false;
		this.isEYOffice = false;
		this.isLocal = (location.protocol=="file:");

		// member fields
		this.viewingID = 0;
		this.testForProgramID = 0;
		this.playerManager = null;
		this.logTimer = null;
		this.eventLogCallBack = eventLogCallBack;
		this.slideCurrentValue = null;
		this.segmentToGoTo = null;
		this.volumeDragging = false;
		this.volumeHead = null;
		this.volumeSlider = null;
		this.volumeXOffset = 0;
		this.volumeLeft = 0;
		this.volumeRight = 0;
		this.volumeRange = 0;
		this.openFeedbackAtEnd = false;
		this.thisPage = "play.aspx";
		this.helpPage = "pages/help/simple.aspx";
		this.helpWindowFeatures = "width=564,height=500,toolbar=0,location=0,directories=0,status=1,menubar=0,scrollbars=1,resizable=1,alwaysRaised=1,titlebar=0";
		this.feedbackPage = "pages/feedback/";
		this.feedbackWindowFeatures = "width=470,height=250,toolbar=0,location=0,directories=0,status=1,menubar=0,scrollbars=1,resizable=1,alwaysRaised=1,titlebar=0";
		this.mediaSecondaryEventsObject = null;
		
		// main starting point
		this.pageLoaded = function(trapScriptErrors) {
			if (trapScriptErrors) window.onerror = this.trapScriptError;
			
			var p = location.pathname.lastIndexOf("/");
			if (p>=0 && !this.isLocal) this.thisPage = location.pathname.substring(p+1,location.pathname.length);
			
			var mp = Browser.getObject("mediaPlayer");
			this.startPlayer(mp);
			
			this.setupRollovers();
			this.setupControlDisplayOptions();
		}
		this.pageUnloaded = function() {
			if (this.playerManager) {
				this.playerManager.stop();
			}
		}


		// flag-setting methods to call from main page
		this.setViewingID = function(viewingID) {
			this.viewingID = viewingID;
		}
		this.setTestForProgramID = function(testForProgramID) {
			this.testForProgramID = testForProgramID;
		}
		this.setEYOffice = function() {
			this.isEYOffice = true;
		}
		this.setAudioOnly = function() {
			this.isAudioOnly = true;
		}
		this.setKontiki = function() {
			this.isKontiki = true;
		}
		this.setDownloadable = function() {
			this.isDownloadable = true;
		}
		this.setTelephone = function() {
			this.isTelephone = true;
		}
		this.setOpenFeedbackAtEnd = function(enable) {
			this.openFeedbackAtEnd = enable;
		}
		this.setFeedbackPage = function(newPage, newFeatures) {
			if (newPage) this.feedbackPage = newPage;
			if (newFeatures) this.feedbackWindowFeatures = newFeatures;
		}
		this.setHelpPage = function(newPage, newFeatures) {
			if (newPage) this.helpPage = newPage;
			if (newFeatures) this.helpWindowFeatures = newFeatures;
		}
		/*
			assign an object with methods to call when certain media player events occur:
				eventHandlerObject.mediaPlaying()
				eventHandlerObject.mediaStopped()
				eventHandlerObject.mediaChanging()
				eventHandlerObject.mediaScriptEvent(command,argument)
				eventHandlerObject.mediaMarkerHit(markerNum)
				eventHandlerObject.mediaError(error)
		*/
		this.setMediaSecondaryEvents = function(eventHandlerObject) {
			this.mediaSecondaryEventsObject = eventHandlerObject;
		}
		this.setKontikiPodcastPackageCreation = function() {
			this.setPodcast();
		}
		this.setPodcast = function(podcastMediaPath) {
			var e = Browser.getObject("podcastButton");
			var mp = Browser.getObject("mediaPlayer");
			if (e!=null && mp!=null) {
				try {
					if (podcastMediaPath!=null) e.href = podcastMediaPath;
					else e.href = mp.URL;
					if (this.isiTunesAvailable()) {
						Browser.displayElement("itunesButton","inline");
					} else {
						Browser.displayElement("podcastButton","inline");
					}
				} catch (exc) {
				}
			}
		}
		
		// initialize and start media player and event log
		this.startPlayer = function(mp) {
			if (mp!=null) {
				this.playerManager = new MediaPlayerManager(mp);
				if (this.playerManager) {
					this.playerManager.startEventLog(this.viewingID, this.testForProgramID);
					var p = location.search.indexOf(SEGMENT_CMD);
					if (p>=0) {
						var n = parseInt(location.search.substring(p+SEGMENT_CMD.length,location.search.length));
						if (!isNaN(n)) {
							this.segmentToGoTo = n;
							try {
								webcastSegments.showSegmentDetails(n);
							} catch (e) { }
						}
					}
					this.volumeHead = Browser.getObject("volumeHead");
					this.volumeSlider = Browser.getObject("volumeSlider");
					try {
						var volumeCmdPos = location.search.indexOf(VOLUME_CMD);
						if (volumeCmdPos>=0) {
							var v = parseInt(location.search.substring(volumeCmdPos + VOLUME_CMD.length, location.search.length));
							this.setVolume(v);
						}
					} catch (e) {
					}
					if (this.playerManager.isAutoStart()) this.showConnectingMessage();
					if (this.playerManager.isFlash) this.onBeginPlaying();
					this.setupPlayControls();
				}
			}
		}
			
		// display-related methods:
		this.setupRollovers = function() {
			Browser.applyRollover("rewindButton");
			Browser.applyRollover("fastforwardButton");
			Browser.applyRollover("playPauseButton",["pause","play"]);
			Browser.applyRollover("playStopButton",["stop","play"]);
			Browser.applyRollover("fullScreenButton");
			Browser.applyRollover("volumeHead");
			Browser.applyRollover("helpButton");
			Browser.applyRollover("optionsButton");
			Browser.applyRollover("feedbackButton");
			Browser.applyRollover("podcastButton");
			Browser.applyRollover("itunesButton");
		}
		this.setupPlayControls = function() {
			Browser.displayElement("playPauseButton","inline");
		}
		this.showConnectingMessage = function() {
			if (!this.playerManager.isRM) Expand.expandItem("messages","Connecting",true);
			if (this.isEYOffice) Browser.displayElement("firewallPromptWarning", "inline");
		}
		this.setupControlDisplayOptions = function() {
			if (location.search.indexOf(COMPACT1_CMD)>=0) {
				Browser.displayElement("buttonSeparator","none");
				Browser.displayElement("optionsViewLabel","none");
			} else if (location.search.indexOf(COMPACT2_CMD)>=0) {
				Browser.displayElement("buttonSeparator","none");
				Browser.displayElement("optionsViewLabel","none");
				Browser.displayElement("fullScreenButton","none");
			} else if (location.search.indexOf(COMPACT3_CMD)>=0) {
				Browser.displayElement("buttonSeparator","none");
				Browser.displayElement("optionsViewLabel","none");
				Browser.displayElement("fullScreenButton","none");
				Browser.displayElement("feedbackButton","none");
				Browser.displayElement("helpButton","none");
				Browser.displayElement("messageArea","none");
			}
			if (this.isLocal) {
				Browser.displayElement("buttonSeparator","none");
				Browser.displayElement("optionsViewLabel","none");
				Browser.displayElement("optionsButton","none");
			}
			if (location.search.indexOf(OPTIONS_OFF_CMD)>=0) {
				// show button, but hide options
				Browser.displayElement("optionsButton","inline");
			} else if (location.search.indexOf(OPTIONS_HIDE_CMD)>=0) {
				// hide options and button
				Browser.displayElement("optionsButton","none");
			} else {
				// default: show options, but hide button
				this.showOptionsPanel();
				Browser.displayElement("optionsButton","none");
			}
		}
		this.displayPlayingFeatures = function() {
			if (this.playerManager.isAudioOnly()) this.playerManager.hideVideo();
			else this.playerManager.showVideo();
			Browser.changeRolloverState("playStopButton", "stop");
			Browser.changeRolloverState("playPauseButton", "pause");
			Browser.displayElement("fullScreenButton",this.playerManager.isAudioOnly()
				|| (location.search.indexOf(COMPACT2_CMD)>=0) || (location.search.indexOf(COMPACT3_CMD)>=0) ? "none" : "inline");
			if (this.playerManager.canPause()) {
				Browser.displayElement("playStopButton","none");
				Browser.displayElement("playPauseButton","inline");
				Browser.displayElement("rewindButton","inline");
				Browser.displayElement("fastforwardButton","inline");
				if (!this.playerManager.isRM) Expand.expandItem("messages","Unicast",true);
				try {
					var minutes = Math.max(1, Math.floor(this.playerManager.getDuration()/60));
					Browser.getObject("mediaDuration").innerText = "("+minutes + " minute(s) total duration)";
				} catch (e) { }
			} else {
				// live or multicast stream features
				Browser.displayElement("playStopButton","inline");
				Browser.displayElement("playPauseButton","none");
				if (!this.playerManager.isRM)  {
					if (this.playerManager.getProtocol()=="multicast") Expand.expandItem("messages","Multicast",true);
					else Expand.expandItem("messages","Live",true);
				}
			}
			// position volume based on current volume
			try {
			Browser.displayElement("volumeControl","inline");
			if (this.volumeSlider!=null) {
				this.volumeLeft = this.volumeSlider.offsetLeft + VOLUME_OFFSET_LEFT;
				this.volumeRight = this.volumeLeft + parseInt(this.volumeSlider.style.width) - VOLUME_OFFSET_RIGHT;
				this.volumeRange = this.volumeRight - this.volumeLeft;
				this.volumeHead.style.left = this.volumeLeft + parseInt(this.playerManager.getVolume()*this.volumeRange/100) + "px";
			}
	        } catch(e) { }
		}
		this.displayStopFeatures = function() {
			if (!this.playerManager.isRM) {
				if (this.playerManager.isPaused()) Expand.expandItem("messages","Paused",true);
				else {
					Expand.expandItem("messages","Stopped",true);
					if (this.openFeedbackAtEnd) this.showFeedbackForm();
				}
			}
			Browser.changeRolloverState("playStopButton", "play");
			Browser.changeRolloverState("playPauseButton", "play");
		}
		
		this.togglePlay = function(stopIfPlaying) {
			if (this.playerManager) {
				if (stopIfPlaying && this.playerManager.isPlaying()) {
					this.stop();
				} else {
					var newSate = this.playerManager.togglePlay();
					if (newSate=="stop") {
						this.onStopPlaying();
						return(false);
					} else if (newSate=="pause") {
						this.onStopPlaying();
						return(true);
					} else {
						this.showConnectingMessage();
						Browser.changeRolloverState("playStopButton", "stop");
						Browser.changeRolloverState("playPauseButton", "pause");
						return(true);
					}
				}
			} return(false);
		}
		this.stop = function() {
			if (this.playerManager) this.playerManager.stop();
			this.onStopPlaying();
		}
		this.rewind = function() {
			if (this.playerManager) {
				this.playerManager.mediaPlayer.controls.fastReverse(); 
				Browser.changeRolloverState("playPauseButton", "play");
			}
		}
		this.fastforward = function() {
			if (this.playerManager) {
				this.playerManager.mediaPlayer.controls.fastForward(); 
				Browser.changeRolloverState("playPauseButton", "play");
			}
		}

		this.onBeginPlaying = function() {
			if (this.playerManager) {
				if (this.eventLogCallBack!=null) {
					// save event log and set interval to automatically save log every so often
					if (this.logTimer!=null) clearInterval(this.logTimer);
					this.saveEventLog();
					this.logTimer = setInterval(this.eventLogCallBack, LOG_TIMER_INTERVAL);
				}
				if (this.segmentToGoTo!=null) this.goToSegment(this.segmentToGoTo);
				this.displayPlayingFeatures();
			}
		}
		this.onStopPlaying = function() {
			if (this.playerManager!=null && this.logTimer!=null) {
				// stop log saver and save event log
				clearInterval(this.logTimer);
				this.logTimer = null;
				this.saveEventLog();
				
				this.displayStopFeatures();
			}
		}

		this.setVolume = function(volumeLevel){
			if (this.playerManager && volumeLevel>=0 && volumeLevel<=100) this.playerManager.setVolume(volumeLevel);
		}
		this.getVolume = function(){
			if (this.playerManager) return(this.playerManager.getVolume());
			else return(0);
		}
		this.toggleVolume = function(){
			if (this.playerManager) {
				if (this.playerManager.getVolume()==0) {
					this.playerManager.setVolume(100);
					return("on");
				} else {
					this.playerManager.setVolume(0);
					return("off");
				}
			} else return("n/a");
		}
		this.interpretVolumeClick = function(event) {
			var evt = Browser.getEvent(event);
			if (evt) {
				try {
					var newLeft = Browser.getMouseX(evt) - (parseInt(this.volumeHead.style.width));
					this.volumeHead.style.left= Math.min(this.volumeRight, Math.max(this.volumeLeft, newLeft)) + "px";
					this.setVolume(Math.round((this.volumeHead.offsetLeft - this.volumeLeft) / this.volumeRange * 100));
				} catch (e) { }
			}
		}
		this.volumeDragStart = function(event) {
			var evt = Browser.getEvent(event);
			if (evt) {
				this.volumeDragging = true;
				this.volumeXOffset = Browser.getMouseX(evt) - this.volumeHead.offsetLeft;
			} else this.volumeDragging = false;
		}
		this.volumeDragChange = function(event) {
			var evt = Browser.getEvent(event);
			if (evt && this.volumeDragging) {
				this.volumeHead.style.left= Math.min(this.volumeRight, Math.max(this.volumeLeft, Browser.getMouseX(evt) - this.volumeXOffset)) + "px";
				this.setVolume(Math.round((this.volumeHead.offsetLeft - this.volumeLeft) / this.volumeRange * 100));
			}
			if (Browser.isIE) {
				evt.cancelBubble = true;
				evt.returnValue = false;
			} else { try { evt.preventDefault(); } catch (e) { } }
		}
		this.volumeDragEnd = function(event) {
			this.volumeDragging = false;
		}
		
		this.toggleFullScreen = function() {
			if (this.playerManager && this.playerManager.isPlaying() && this.playerManager.canPlayFullScreen()) {
				alert("PLEASE NOTE: To exit full-screen mode, press the ESC key.");
				this.playerManager.showFullScreen();
			} else {
				alert("Full screen mode is not available for an audio-only stream. Click the options button and try a different selection.");
			}
		}
		this.goToSegment = function(markerNumber, clipNumber) {
			if (clipNumber>0) {
				if (this.playerManager.goToClipNumber(clipNumber)) {
					// new clip
					Expand.expandItem("messages","Seeking",true);
					this.segmentToGoTo = markerNumber;
				} else {
					// same clip
					if (this.playerManager.isPlaying()) {
						// if already playing, jump to marker
						if (this.playerManager.getCurrentMarker()!=markerNumber) Expand.expandItem("messages","Seeking",true);
						this.segmentToGoTo = null;
						this.playerManager.goToMarkerNumber(markerNumber);
					} else {
						// if not playing, start playing first
						Expand.expandItem("messages","Seeking",true);
						this.segmentToGoTo = markerNumber;
						this.playerManager.play();
					}
				}
			} else if (this.playerManager && markerNumber>0) {
				// no clip specified, just jump to marker
				Expand.expandItem("messages","Seeking",true);
				this.segmentToGoTo = null;
				this.playerManager.goToMarkerNumber(markerNumber);
			}
		}
		this.dispatchScriptEvent = function(command, argument) {
			switch (command) {
				case "slide":
					if (argument!=this.slideCurrentValue) {
						try {
							webcastSlides.setSlide(argument);
						} catch (e) { }
						try {
							// update segment for multi-clip media using slide number
							if (this.playerManager.getClipCount()>1)
								webcastSegments.showSegmentDetails(parseInt(argument));
						} catch (e) { }
						this.slideCurrentValue = argument;
					}
					break;
			}
		}
		
		// event handlers
		this.trapOpenStateChange = function(oldState, newState) {
			if (this.playerManager) {
				var stateName = this.playerManager.trapOpenStateChange(oldState, newState);
				if (stateName=="MediaChanging" && this.mediaSecondaryEventsObject!=null) {
					try {
						this.mediaSecondaryEventsObject.mediaChanging();
					} catch (e) { }
				}
			}
		}
		this.trapBuffering = function(isBuffering) {
			if (this.playerManager) this.playerManager.trapBuffering(isBuffering);
			if (!isBuffering) this.onBeginPlaying();
		}
		this.trapPlayStateChange = function(oldState, newState) {
			if (this.playerManager) {
				var stateName = this.playerManager.trapPlayStateChange(oldState, newState);
				if (this.playerManager.isPlaying()) {
					this.onBeginPlaying();
					if (this.mediaSecondaryEventsObject!=null) {
						try {
							this.mediaSecondaryEventsObject.mediaPlaying();
						} catch (e) { }
					}
				} else if (stateName=="stopped" || stateName=="paused" || stateName=="waiting") {
					this.onStopPlaying();
					if (this.mediaSecondaryEventsObject!=null) {
						try {
							this.mediaSecondaryEventsObject.mediaStopped();
						} catch (e) { }
					}
				}
			}
		}
		this.trapScriptEvent = function(command,argument) {
			if (this.playerManager) {
				this.playerManager.trapScriptEvent(command,argument);
				this.onBeginPlaying();
				if (command!=null && command.length>0) this.dispatchScriptEvent(command.toLowerCase(), argument);
			}
			if (this.mediaSecondaryEventsObject!=null) {
				try {
					this.mediaSecondaryEventsObject.mediaScriptEvent(command,argument);
				} catch (e) { }
			}
		}
		this.trapMarkerHit = function(markerNum) {
			if (this.playerManager) {
				this.playerManager.trapMarkerHit(markerNum);
				this.onBeginPlaying();
				try {
					// update segment if the media only has one clip
					if (this.playerManager.getClipCount()==1)
						webcastSegments.showSegmentDetails(parseInt(markerNum));
				} catch (e) { }
			}
			if (this.mediaSecondaryEventsObject!=null) {
				try {
					this.mediaSecondaryEventsObject.mediaMarkerHit(markerNum);
				} catch (e) { }
			}
		}
		this.trapWarning = function(type,parameter,description) {
			if (this.playerManager) {
				this.playerManager.trapWarning(type,parameter,description);
			}
		}
		this.trapMediaError = function(severity,rma_code,user_code,user_string,more_info_url,error) {
			this.stop();
			Expand.expandItem("messages","Error",true);
			if (this.playerManager) this.playerManager.trapError(error);
			this.saveEventLog();
			if (this.mediaSecondaryEventsObject!=null) {
				try {
					this.mediaSecondaryEventsObject.mediaError(error);
				} catch (e) { }
			}
		}
		this.trapScriptError = function(message,url,lineNumber) {
			status = "Error: "+message+" on line "+lineNumber;
			if (this.playerManager) this.playerManager.trapError(message,url,lineNumber);
			return(false);
		}

		// save event log to server
		this.saveEventLog = function() {
			if (!this.isLocal && this.viewingID>0 && this.playerManager) {
				status = "Saving playback quality data...";
				XmlUtility.postXml(MEDIA_LOG_RECORDER, WebcastPlayer_dataPosted, this.playerManager.getStatusLogXml());
				this.playerManager.clearStatusLog();
			}
		}

		// non-media related actions
		this.showOptionsPanel = function(forceOpen) {
			if (Expand) Expand.expandItem("options", "Selector", forceOpen);
		}
		this.switchMedia = function(Media_id) {
			if (Media_id!=null) {
				var commands = [];
				var append = true;
				if (location.search.length>0) {
					commands = location.search.substring(1,location.search.length).split("&");
					for (var q=0; q<commands.length; q++) {
						if (commands[q].indexOf(MEDIA_ID_KEY)==0) {
							commands[q] = MEDIA_ID_KEY+"="+Media_id;
							append = false;
						}
					}
				}
				if (append) commands[commands.length] = MEDIA_ID_KEY+"="+Media_id;
				this.openFeedbackAtEnd = false;
				location = this.thisPage+"?"+commands.join("&");
			}
		}
		this.clearUser = function() {
			//document.cookie = "wv2uid=; expires=1 Jan 1980 01:00:00 UTC";
			//location.reload(true);
		}
		this.openHelp = function(linkElement) {
			var url = null;
			if (this.isLocal) {
				url = this.convertUrlFromLink(linkElement, this.helpPage);
				if (!confirm(NETWORK_REQ_MESSAGE)) return;
			} else {
				url = this.helpPage;
			}
			if (url) open(url, "helpwindow", this.helpWindowFeatures);
		}
		this.showFeedbackForm = function(linkElement) {
			var url = null;
			if (this.isLocal) {
				url = this.convertUrlFromLink(linkElement, this.feedbackPage);
				if (!confirm(NETWORK_REQ_MESSAGE)) return;
			} else {
				url = this.feedbackPage;
			}
			if (url) open(url, "feedback", this.feedbackWindowFeatures);
			this.openFeedbackAtEnd = false;
		}
		this.convertUrlFromLink = function(linkElement, replacementPage) {
			try {
				var url = linkElement.href;
				var p = url.indexOf(this.thisPage);
				url = url.substring(0,p) + replacementPage + url.substring(p+this.thisPage.length, url.length);
				return(url);
			} catch (e) {
				return(null);
			}
		}
		this.addToiTunes = function(podcastMediaPath) {
			var e = Browser.getObject("itunesButton");
			var mp = Browser.getObject("mediaPlayer");
			var iTunesApp = null;
			if (e!=null && (mp!=null || podcastMediaPath!=null)) {
				try {
					if (podcastMediaPath==null) podcastMediaPath= mp.URL;
					iTunesApp = new ActiveXObject("EYiTunesAdd.clsAddToiTunes");
					for (var extloop = 0; extloop < PODCAST_EXTENSIONS.length; ++extloop) {
						var ext = PODCAST_EXTENSIONS[extloop];
						if ((podcastMediaPath.lastIndexOf(ext)+ext.length) == podcastMediaPath.length)
						{
							iTunesApp.FileName = podcastMediaPath;
							iTunesApp.Add();
						}
					}
				} catch (exc) {
					alert("Unable to add the podcast to your iTunes library. Do you have iTunes version 7 or later installed?");
					iTunesApp = null;
				}
			}
		}
		this.isiTunesAvailable = function() {
			try {
				var iTunesApp = new ActiveXObject("EYiTunesAdd.clsAddToiTunes");
				var isAvailable = iTunesApp.GotiTunes;
				iTunesApp = null;
				return(isAvailable);
			} catch (e) {
				return(false);
			}
		}


		return(this);
}

function WebcastPlayer_EventLogSaver() {
	webcastPlayer.saveEventLog();
}
function WebcastPlayer_dataPosted() {
	if (XmlUtility.isRequestError()) status = XmlUtility.getStatus();
	else if (XmlUtility.isRequestComplete()) status = "";
}

function specialOptions(eventArg) {
	var evt = Browser.getEvent(eventArg);
	if (evt && evt.shiftKey) webcastPlayer.clearUser();
}


var webcastPlayer = new WebcastPlayerClass(WebcastPlayer_EventLogSaver);

