/****************************
 * EmbedVideo Class
 * 
 *  This class embeds a video on a web page using a plugin player designated in a separate EVPlugin class.
 *  
 *  Currently will play movies in QuickTime, Flash, and WMP
 */
var EmbedVideo = new Class({

	Implements: [Events, Options],

	//default options
	options: {
		movieid:"vidplayer",
		movieTitle:"",
		dirHome:"",
		plugin:"quicktime",
		pluginError:"You are missing the required plugins to play this video.",
		pluginCaptionFile:"",
		useDefaultExt:true, //use the default file extension for the movie file, override passed in ext.
		autoplay: false,
		poster:"", //url to poster image to use,
		posterElement:false,//id of poster element to use
		bgcolor:"FFFFFF", //background color of player
		postevents: true,
		jsenabled:true,
		controller:true,
		noscale:false, //default to scale movie to size of player
		path:"", //movie url or src
		h:0,
		w:0,
		restartAtEnd:false
		
	},
	
	addPlugin:function(pluginObj){
		
		if (pluginObj.name) {
			this.plugins[pluginObj.name] = pluginObj;
		}else{
			return false;
		}
	},
	
	//supported plugins
	plugins:{

		none:{ //default when no plugins exist
			priority:1000,
			isInstalled: function(){ return true;},
			genEmbed:function(options){ return '<span style="color:#fff">You are missing the required plugins to play our video.<br/>You must have at least Flash 9 or Quicktime 7.2 installed.</span>';},
			controlHeight:0,
			fileExt:""
		}
	},
	
	setPluginDefaultExt:function(plugin,ext){
		
		//change default
		this.plugins[plugin].fileExt = ext;
		
		//update default path
		this.updatePathExt();
	},
	
	getPlugin:function(){
		return this.plugins[this.options.plugin];
	},
	
	events:{
		
		begin:$lambda(false),
		load:$lambda(false),
		ready:$lambda(false),
		play:$lambda(false),
		pause:$lambda(false),
		stop:$lambda(false),
		ended:$lambda(false)
		
	},
	
	//browser environment
	env:{
		os:"",
		browser:"",
		version:""	
	},
	
	//initialize the movie
	initialize: function(element, options){
		
		//don't do anything if element not found
		if(!element) return false;
		
		
		//get any option settings from link element
		this.initElemOptions(element);
		
		
		
		
		//initialize plugins
		
		if (this.options.postevents) {
			
			//used when events are required to be supported by QuickTime
			this.addPlugin(new QTPluginEvents({priority: 1}));
			
		}
		else {
			
			//all quicktime versions allowed
			this.addPlugin(new QTPlugin({priority: 1}));
			
		}
		this.addPlugin(new ScreenPlayerPlugin({priority:2}));
		this.addPlugin(new WMPlugin({priority:3}));
			
		
		
		
		//set any options passed in deliberately, overrides link set options	
		this.setOptions(options);
		
		
		//choose and initialize player plugin
		this.initPlugin();
		
		//init browser environment
		this.initEnv();
		
		this.posterType = Poster;
		
		this.initElem = element;
		
		
	},
	
	initEnv:function(){
		
		//set browser and browser version
		if(Browser.Engine.trident){
			this.env.browser= "ie";
			if(Browser.Engine.trident4) this.env.version="6";
			if(Browser.Engine.trident5) this.env.version="7";
		}else if(Browser.Engine.gecko){
			this.env.browser="firefox";//most likely firefox
			var verNum = navigator.userAgent.split('Firefox/')[1].substring(0,1);
			if(verNum=="3"){
				this.env.version="3";
			}else if(verNum="2"){
				this.env.version="2";
			};
		}else if(Browser.Engine.webkit){
			this.env.browser="safari";//most likely safari
			if(Browser.Engine.webkit419) this.env.version="2";
			if(Browser.Engine.webkit420) this.env.version="3";
		}
		
		//set os
		if (Browser.Platform.win) {
			this.env.os = "windows";
		} else if (Browser.Platform.mac) {
			this.env.os = "mac";
		}
		
	},
	
	embed:function(){
		
		//add controller height
		if(this.options.controller)
			this.options.h = parseInt(this.options.h) + parseInt(this.plugins[this.options.plugin].controlHeight);

		
		//add an accessible variable for this video embed instance in the dom.
		document[this.options.movieid + 'domaccess'] = this;
		
		if (this.options.poster != "") {
			
			//draw or update poster
			var posterElem = this.drawposter(this.initElem);
			
			//create movie wrapper div and reference
			this.createMovieWrapper(posterElem);
			
			//should always start playing after clicking poster
			this.options.autoplay = true; 
			
		}
		else 
		{	
			//create movie wrapper div and reference
			this.createMovieWrapper(this.initElem);
			
			this.draw();
			
		}
	},
	
	replace:function(newoptions){
		//reset any options passed via call to replace	
		this.setOptions(newoptions);
		
		//redraw player or poster with new options set
		if (this.options.poster != "") {
			
			var posterElem = this.drawposter(this.movieElem);
			
			//create movie wrapper div and reference
			this.createMovieWrapper(posterElem);
			
			//should always start playing after clicking poster
			this.options.autoplay = true; 
		}
		else {
			//create movie wrapper div and reference
			
			this.draw();
		}
	},
	
	initPlugin:function(){
		
		
		//remove any plugin references that are not installed on this browser
		for(var plugin in this.plugins){
			
			if(!this.plugins[plugin].isInstalled()) delete this.plugins[plugin];
		}
		
		
		//choose plugin for use based on preference and availability
		this.options.plugin = this.choosePlugin(this.options.plugin);
		
		//choose default extension for plugin and update path, unless specified otherwise
		this.updatePathExt();
		
		
	},
	
	//updates the current path with default extension of current plugin
	updatePathExt:function(){
		
		
		if(this.options.useDefaultExt){
			
			var splitPathArr = this.options.path.split('.');
			var lastIndex = splitPathArr.length-1;
			
			splitPathArr[lastIndex] = this.plugins[this.options.plugin].fileExt;
			this.options.path = splitPathArr.join('.');
			

		}
	},
	
	choosePlugin:function(preferredPlugin){
		
		//check to see if preferred plugin  is available
		if(this.plugins[preferredPlugin]){
			return preferredPlugin;
		}
		
		//choose an alternative plugin if preferred not available
		var altPlugin="";
		var p=100;
		for (var plugin in this.plugins) {
			if(this.plugins[plugin].priority < p){
				p=this.plugins[plugin].priority;
				altPlugin = plugin;
			} 
		}
		
		return altPlugin;
	},
	
	initElemOptions:function(elem){
		
		//get movie id from link element
		this.options.movieid = elem.id;
		
		//get movie path from link element
		this.options.path = elem.href;
		
		//set width from link
		var elWidth = elem.getStyle('width');
		if(elWidth!="")
			this.options.w = elWidth.substring(0,elWidth.length-2);
		
		//set height from link
		var elHeight = elem.getStyle('height');
		if(elHeight!="")
			this.options.h = elHeight.substring(0,elHeight.length-2);
		
		//set poster image
		var posterSRC = elem.getStyle('background-image');
		if(posterSRC!=""){
			posterSRC = posterSRC.substring(4,posterSRC.length);
			this.options.poster = posterSRC.substring(0,posterSRC.length-1);
		}
		
		//get movie title
		this.options.movieTitle = $(elem).get('text');
		
		
		//set background color for player
		var bgcolor = elem.getStyle('background-color');
		if(bgcolor!=""){
			this.options.bgcolor = bgcolor.substring(1,bgcolor.length);
		}
		
		//set autoplay
		if(elem.hasClass("autoplay")) this.options.autoplay = true;
			else this.options.autoplay = false;
		
		//set controller
		if(elem.hasClass("controller")) this.options.controller = true;
			else this.options.controller = false;
			
		//set scale rules
		if(elem.hasClass("noscale")) this.options.noscale = true;
			else this.options.noscale = false;
		
		//set end rules (currently only works in jsplayer
		if(elem.hasClass("restartAtEnd")) this.options.restartAtEnd = true;
			else this.options.restartAtEnd = false;
		
		//set end poster element
		this.options.posterElement = this.getPropValue("posterElement",elem);
		
	},
	
	//get a property value passed in using class parameter
	getPropValue:function(propName,screenElement){
		
		if (!screenElement) {
			screenElement = this.initElem
		};
		
		//split each class into array
		var propArray = screenElement.get('class').split(' ');
		
		
		for(var x=0;x<propArray.length;x++){
			
			if(propArray[x]==propName){
				
				//property is true false, if exists then true
				return true;
				
			}else if(propArray[x].substring(0,propName.length)==propName){
				
				//property is string value and is in format propName-propvalue 
				var prop = propArray[x].split('-');
				return prop[1];
			}
			
			
			
		}
		
		return false;
		
	},
	addEventAction:function(event,func){
		
		var oldAction = this.events[event];
		//var oldAction = this.events[event].action;
		var newAction = function(){
			if(oldAction)
				oldAction();
			func();
		}
		this.events[event] = newAction;
		//this.events[event].action = newAction;
		
	},
	
	createMovieWrapper:function(elemToWrap){
		//create a wrapper div for link element
		var movieDiv = new Element("div",{});
		$(movieDiv).setStyle('height',this.options.h + "px");
		$(movieDiv).setStyle('width',this.options.w + "px");
		$(movieDiv).setStyle('background-color','#' + this.options.bgcolor);
		$(movieDiv).setStyle('position','relative');//added for floating bug
		
		$(movieDiv).wraps(elemToWrap);
		this.movieElem = movieDiv;
	},
	
	drawposter:function(elem,optPoster){
	
		var posterOptions = {
				type: "link",
				movieid: this.options.movieid,
				movieTitle: this.options.movieTitle,
				path: this.options.path,
				src: this.options.poster,
				height: this.options.h,
				width: this.options.w,
				posterElem:this.options.posterElement
			
			}
			
		if (!optPoster) {
			posterOptions.click = this.draw.bind(this);
			var newPoster = new this.posterType(posterOptions);
			
			var poster = newPoster.postOver(elem);
		
			this.movieElem = poster;
		
		}else{
			
			var newPoster = optPoster;
			
			var poster = newPoster.postOver(elem);
			$(poster).replaces(this.movieElem);
			
			this.movieElem = poster;
		}
		
		
		
		
		
		return poster;
		
	},
	
	//determine if plugin needs iframe to run properly
	needsIFrame:function(){
		var isNeeded = false;
		if(this.options.plugin == "quicktime"){
			if(this.env.browser=="ie" || this.env.browser=="firefox"){
				isNeeded=true;
			}
		} 
		return isNeeded;	
	},
	
	embedText:"",
	
	draw: function(e){
		
		
		//check to see if generation needs iframe
		this.options.needsIFrame = this.needsIFrame();
		
		
		//add an accessible variable for this video embed instance in the dom.
		//document[this.options.movieid + 'domaccess'] = this;
		
		//generate html for player plugin
		this.movieElem = this.plugins[this.options.plugin].genEmbed(this.options,this.movieElem);
		
		//attach events to plugins
		this.plugins[this.options.plugin].registerEvents(this.options.movieid, this.events);
		
		//TO DO: must find a way to add frame event code from plugin, instead of outside plugin in frame html
	   	
		this.endDraw();
		if (e) {//stop any click event from propagating
			e = new Event(e).stop();
			
		}
	},
	
	endDraw:function(){
		//do nothing, can be defined in parent classes
	}

});


/*******************
 * 
 *  EVPlugin Class (Abstract)
 *   
 *   The EmbedVideo Class depends on having an associated video player plugin associated with it to run.
 *   The EVPlugin is an abstracted class that is the base class for plugins that EmbedVideo can embed.
 *   
 * @param {string} name of plugin 
 * @param {string} name of default file extension that plugin will play
 * @param {Object} options
 */

var EVPlugin = new Class({

	Implements: Options,
	

	initialize:function(name,fileExt,options){
		
		this.setOptions(options);
		
		if (this.options.priority) {
			this.priority = this.options.priority;
		}
		
		this.name = name;
		this.fileExt = fileExt;
	},
	
	name:"",
	
	priority:1,
	
	isInstalled:function(){return true},
	
	genEmbed:function(options,elemToReplace){ return elemToReplace},
	
	controlHeight:0,
	
	fileExt:"",
	
	events:{
		begin:"begin",
			
		load:"load",
			
		ready:"ready",
		
		play:"play",
				
		pause:"pause",
		
		ended:"ended"
	}
	
});




			


			
/*******************
 * 
 *  QTPlugin Class
 *   
 *   The QTPlugin class handles the QuickTime web plugin.
 *   
 * @param {Object} options
 */
var QTPlugin = new Class({

	Extends: EVPlugin,
	
	initialize:function(options){
		
		this.parent("quicktime","mov",options);
		this.controlHeight = 16;
		
		
		//add qt events to mootools native event binder
		for (var event in this.events){
			Element.NativeEvents[this.events[event]]=2;
		}
		
	},
	
	registerEvents:function(objectId,eventList,docObj){
	
		
		for (var event in this.events) {
			if (eventList[event]) {
				
				RegisterListener(this.events[event], objectId, 'embed_' + objectId, eventList[event]);
			}
		}
					
	},
	
							
	isInstalled:function(){return detectQuickTime();},
	
	
	genQuicktime:function (options){
		var movieEmbedId = "embed_" + options.movieid;
		var movieId = options.movieid;
		
		if(options.scale){
			var scaleVal ="aspect";
		}else{
			var scaleVal = "tofit";
		}
		
		
		var embedVideoTxt = QT_GenerateOBJECTText_XHTML(options.path, options.w, options.h, '', 'EnableJavaScript', boolToString(options.jsenabled), 'postdomevents', boolToString(options.postevents), 'emb#NAME', movieId, 'obj#id', movieId, 'emb#id', movieEmbedId,'bgcolor',options.bgcolor, 'controller', boolToString(options.controller), 'autoplay', boolToString(options.autoplay),'scale',scaleVal);
		
		return embedVideoTxt;
	},
	
	genEmbed:function(options,elemToReplace){ 
		
		var newHtml = this.genQuicktime(options);
		
		if (!options.needsIFrame) {
			//generate html for embed
			
			//add a div wrapper to stop strange floating errors
			var replaceDiv = new Element("div",{});
			$(replaceDiv).setStyle('position',"relative");
			$(replaceDiv).setStyle('height',options.h + "px");
			$(replaceDiv).setStyle('width',options.w + "px");
			
			var newObj = replaceDiv.set('html', (newHtml));
			
			//replace stand-in element with embed html
			return newObj.replaces($(elemToReplace)); //.set('html', (newHtml));
			
		}else{
			//return genQuicktime(options);
			//embed movie within iframe
				
				var playerId = options.movieid;
				
				
				//load global variable with embed html that iframe will reference
				if (!window.embedtext) {
					window.embedtext = new Array();
				}
				window.embedtext[playerId] = newHtml;
				
				//avoid id conflict when iframe is created with existing id
				document.getElementById(options.movieid).id = "temp1234XX";
				
				
				
				
				var frameH = options.h;
				var frameW = options.w;
				var vFrameDir = options.dirHome;
				
				//create new IFrame that requires blank.html file
				var myIFrame = new IFrame({
					id: playerId,
					
					src: vFrameDir + 'vframe.html?playerid=' + playerId,
					
					scrolling: 'no',
					
					border: '0',
					
					frameborder: '0',
					
					styles: {
						width: frameW + "px",
						height: frameH + "px",
						border: 0,
						display: "block"
					}
				
				});
				
				$(myIFrame).replaces(elemToReplace);
				
				//reset movieElem object
				
				return myIFrame;
				
		}
		
	
	},
	
	events:{
		begin:"qt_begin",
			
		load:"qt_load",
			
		ready:"qt_canplay",
		
		play:"qt_play",
				
		pause:"qt_pause",
		
		ended:"qt_ended"
	}
	
});

/*******************
 * 
 *  QTPluginEvents Class
 *   
 *   The QTPlugin class handles the QuickTime web plugin but only 7.2 and higher (for support of dom events).
 *   
 * @param {Object} options
 */
var QTPluginEvents = new Class({
	Extends: QTPlugin,
	isInstalled:function(){
		
		if(getQTVersion() >= 7.2){
				return true;
				
			}else{
				return false;
			}
		}
	
});


/*******************
 * 
 *  ScreenPlayerPlugin Class
 *   
 *   The ScreenPlayerPlugin class handles the ScreenPlayer flash player.
 *   
 * @param {Object} options
 */
var ScreenPlayerPlugin = new Class({

	Extends: EVPlugin,
	
	initialize:function(options){
		
		this.parent("flash","flv",options);
		this.controlHeight = 0;
		
	},
	
	isInstalled:function(){return detectFlash();},
	
	
	genFlash:function(options){
	
		var params ={
	
			allowScriptAccess:"sameDomain",
			allowFullScreen:"false",
			play:boolToString(options.autoplay),
			scale:"exactfit",
			wmode:"window",
			quality:"high",
			bgcolor:options.bgcolor
	
		};
		var attributes={
			align:"middle"
		
		};
		var flashvars={
			playmovie:options.path,
			htmldocref:"document",
			w:options.w,
			h:options.h,
			showcontrols:boolToString(options.controller),
			captionsFile:options.pluginCaptionFile
			
		
		}
		
		var screenplayersrc = options.dirHome + "screenplayer.swf";
		
		swfobject.embedSWF(screenplayersrc, options.movieid, options.w, options.h, '9.0.0', 'http://www.macromedia.com/go/getflashplayer', flashvars, params, attributes);	
		
		return $(options.movieid);
	},
	
	genEmbed:function(options,elemToReplace){ return this.genFlash(options);},
	
	registerEvents:function(objectId,eventList,video){
		
		//create a reference to this object that flash player can access via the document
		//document[objectId + 'flashaccess'] = video;
		
		//may need to change this for IE
		var htmlDocRef = "document";
		
		
		
		//create the function that flash player will fire upon loading
		document.registerSPlayerEvents = function(){
			
			var movieid = objectId;
			
			var addFlashEventListener=function(eventName,functionName){
				document[objectId].RegisterJSListener(eventName,functionName);
			}
			//add event actions to flash
			for (var event in this.events) {
				
				addFlashEventListener(event, htmlDocRef + "." + objectId + "domaccess.events." + event);
					
			}
			
		}.bind(this);
					
	}
	
});


/*******************
 * 
 *  WMPlugin Class
 *   
 *   The WMPlugin class handles the windows media player web plugin.
 *   
 * @param {Object} options
 */
var WMPlugin = new Class({

	Extends: EVPlugin,
	
	initialize:function(options){
		
		this.parent("wmv","wmv",options);
		this.controlHeight = 45;
		
		//add wmp event for testing play state
		Element.NativeEvents['playStateChange']=2;
	},
	
	isInstalled: function(){ return detectWindowsMedia();},
	
	
	genWMV:function(options){
		var movieEmbedId = "embed_" + options.movieid;
		var movieId = options.movieid;
		
		var embedVideoTxt = "<object ";
		
		var attributes = {
			id: movieId,
			width: options.w,
			height: options.h,
			align: "middle",
			classid: "clsid:6BF52A52-394A-11d3-B153-00C04F79FAA6",
			type: "application/x-oleobject"
		}
				
		//add obj attribs
		for (var attrib in attributes) 
			embedVideoTxt += attrib + '="' + attributes[attrib] + '" ';
		
		embedVideoTxt += ">";
		
	
		var params = {
			url: options.path,
			AutoStart: options.autoplay,
			DefaultFrame: "mainFrame",
			uiMode: options.controller ? "full" : "none",
			StretchToFit: options.noscale ? "False" :"True",
			DisplayBackColor:options.bgcolor,
			SendPlayStateChangeEvents:"True"
		}
				
		//add params
		for (var param in params) 
			embedVideoTxt += '<param name="' + param + '" value="' + boolToString(params[param]) + '">';
		
		if (Browser.Engine.gecko) {//for FF wmv plugin
			var embedTag = "<embed ";
			
			var attributes = {
				id: "embed_" + movieId,
				width: options.w,
				height: options.h,
				align: "middle",
				pluginspace: "http://www.microsoft.com/Windows/MediaPlayer/",
				src: options.path,
				type: "application/x-oleobject",
				scale: options.noscale ? "" :"tofit",
				uiMode: options.controller ? "full" : "none",
				DisplayBackColor:options.bgcolor,
				SendPlayStateChangeEvents:"True"
			}
			
			for (var attrib in attributes) 
				embedTag += attrib + '="' + attributes[attrib] + '" ';
			
			for (var param in params) 
				embedTag += param + '="' + params[param] + '" ';
			
			embedTag += "></embed>";
			
			embedVideoTxt += embedTag;
		}
		embedVideoTxt +="</object>";
		
		return embedVideoTxt;
	},
	
	genEmbed:function(options,elemToReplace){ 
	
		var newHtml = this.genWMV(options);
		
		//replace stand-in element with embed html
		return $(elemToReplace).set('html', (newHtml));
	
	},
	
	registerEvents:function(objectId,eventList){
		
		var wmp = new Object();
		wmp = document.getElementById(objectId);
					
		var g_events = this.events;	
		var handleWMVEvents = function(playstate){
		
			for (var event in g_events) {
				if (g_events[event] == playstate) {
					if (eventList[event].action) 
						eventList[event].action();
				}
				
			}
		};
		
		//handle wmp events
		if (wmp.attachEvent) {//if IE
			wmp.attachEvent("playStateChange", handleWMVEvents);
			
		}
	},
	
	events:{
			
		ready:10,
		
		play:3,
				
		pause:2,
		
		stop:1,
		
		ended:8
	}
});

/*******************
 * 
 *  Poster Class
 *   
 *   The EmbedVideo class can show a poster before or after play of a movie.  This class defines how that
 *   poster will look.
 *   
 * @param {Object} options
 */
var Poster = new Class({

	Implements: [Events, Options],
	//default options
	options: {
		type:"link",
		movieid:"",
		movieTitle:"",
		path:"",
		src:"",
		height:0,
		width:0,
		click:$empty
	},
	
	initialize:function(options){
		this.setOptions(options);
		
		
	},
	
	postOver:function(elemToPoster){
		this.posterElem = new Element("a",{
				id:this.options.movieid,
				text:this.options.movieTitle,
				href:this.options.path								
		});
		
		$(this.posterElem).setStyle('display','block');
		$(this.posterElem).setStyle('text-indent','-9000px');
		$(this.posterElem).setStyle('background-image','url(' + this.options.src + ')');
		$(this.posterElem).setStyle('height',this.options.height + "px");
		$(this.posterElem).setStyle('width',this.options.width + "px");
		
		$(this.posterElem).replaces(elemToPoster);
		$(this.posterElem).addEvent('click',this.options.click)
		return this.posterElem;
	}

	
	
});


function boolToString(val){
	if(typeof val =="boolean"){
		if(val) {
			return "True";
		}else{
			return "False";
		}
	}else{
		return val;
	}
}