/**
 * @fileOverview This file contains all Media code
 * @author <a href='http://wiki.element115.net/index.php/User:Schopra'>schopra</a> 
 */

var mediaObject = Class.create(
	/** 
	 * @lends mediaObject.prototype
	 * 
	 */
	{
	// 
	/**
	 * This string array prevents the mediaObject from embedding if sufficient information
	 * is unavailable 
	 * 
	 * NOTE: should we use "href" or "path_media"? both, so neither
	 *  
	 * @property {Array}
	 */
	requiredProperties: ["definition","type","width","height","embed_id"],
	/**
	 * Creates an instance of mediaObject
	 * 
	 * single media object class, constructor requires HTML element
	 * 
	 * should only be accessed through mediaDirectory, otherwise it
	 * may be impossible to keep and access the media's data safely
	 * 
	 * @author schopra
	 * @this {mediaObject}
	 * @param {Object} obj obj.element should equal the element OR obj.assetID should be the assetid
	 * @version 2010 beta 1
	 * @constructs
	 * 
	 */
	initialize: function(obj){
		 if(typeof obj !=="undefined"){
				if(typeof obj.element!=="undefined"){
					this.properties = eHA.elementToObjectLiteral(obj.element);
					this.properties.embed_id = this.properties.id+"";
					this.properties.complete = false;
					this.properties.html = obj.element;
					return this;
				}else{
					if(typeof obj.assetID!=="undefined"){
						// must assume assettype = "Media_C" for AJAX to work
						this.properties = {assetid: obj.assetID,assettype:"Media_C",complete:false};
					}else{
						return false;
					}
				}
		 }else{
			 return false;
		 }
	},
	/**
	 * @function
	 * @returns {boolean} true if this mediaObject has all requiredProperties specified in array
	 */
	hasRequiredProperties: function(){
		for(var i=0;i<this.requiredProperties.length;i++){
			var thisProperty = this.requiredProperties[i];
			if(typeof this.properties[thisProperty]!== "undefined"){
				// property exists, value doesn't matter
			}else{
				return false;
			}
		}
		return true;
	},
	onbeforeinsert: function(callback){
		eval(callback);
	},
	/**
	 * loads complete data with AJAX, sets this.complete = true
	 * executes callback function onComplete
	 * 
	 * @author schopra
	 * @function
	 * @param {function} callback This function is called at the end of onComplete
	 * 
	 */
	loadData: function(callback){
		
		var URL = "/cs/Satellite";
		var pagename = eHA.Site+"/"+this.properties.assettype+"/"+eHA.Site+"/json";
		if(eHA.Site==="demo"){
			URL = "Satellite.php";
			pagename="JSON";
		}
		var parameters = {
		  pagename: pagename,
		  site: eHA.Site,
		  c: this.properties.assettype,
		  cid: this.properties.assetid
		};
		try{
			new Ajax.Request(URL,
				{
					method:'get',
					asynchronous: false,
					parameters: parameters,
					onCreate: function(){
						eHA.log.create(parameters.cid+": AJAX request for JSON created", 3);
					},
					onSuccess: function(transport){
						eHA.log.create(parameters.cid+": AJAX request for JSON succeeded", 3);
					},
					onComplete: function(transport){
						// add transport.responseText to this.properties
						eHA.log.create(parameters.cid+": AJAX request for JSON completed", 3);
						if(transport.responseText){
							eHA.log.create(parameters.cid+": attempting to evaluate JSON and add to mediaObject", 3);
							try{
								var metaData = transport.responseText.evalJSON(true);
								Object.extend(mediaDirectory["child_"+metaData.assetid].properties,metaData);
								if(typeof mediaDirectory["child_"+metaData.assetid].properties.href === "undefined"){
									if(typeof mediaDirectory["child_"+metaData.assetid].properties.path_media!=="undefined"){
										mediaDirectory["child_"+metaData.assetid].properties.href = mediaDirectory["child_"+metaData.assetid].properties.path_media;
									}else{
										eHA.log.create(parameters.cid+": this media has no href or path_media", 1);
									}
								}
								mediaDirectory["child_"+metaData.assetid].properties.complete = true;
								
								mediaDirectory["child_"+metaData.assetid].onbeforeinsert();
								eval(callback);
							}catch(err){
								eHA.log.create(parameters.cid+":"+err.name+" - "+err.message, 1);
							}
						}else{
							eHA.log.create(parameters.cid+": problem with transport.responseText onComplete", 1);
						}
					},
					onFailure: function(){
						eHA.log.create(parameters.cid+": AJAX request for JSON resulted in failure", 1);
					}
				});
		}catch(err){
			eHA.log.create(parameters.cid+":"+err.name+" - "+err.message, 1);
		}
		
	},
	/**
	 * When this function is executed, the mediaObject is placed in the page.
	 * This is the function that should be executed onclick
	 * 
	 * @author schopra
	 * @function
	 */
	initiate: function(){
		
		var usePanels = this.getProperty("usePanels");
		
		if(usePanels){
			panels.appear();
		}
		if(!this.properties.complete && mediaDirectory.useAJAX){
			this.loadData("mediaDirectory.child_"+this.properties.assetid+".insert()");
		}else{
			if(!this.properties.complete && !mediaDirectory.useAJAX){
				eHA.log.create("attempting to load media without AJAX while not complete",2);
			}
			this.insert();
		}
		return false;
	},
	/**
	 * @function
	 * checks property value at 3 levels, Asset-level, Definition-level (from mediaDirectory[definition])
	 * and globally (from mediaDirectory).  If no values are available, will return null or empty
	 * 
	 * @param {String} property
	 * 
	 * @returns propertyValue
	 */
	getProperty: function(property){
		var propertyValue;
		// use Asset-level value for property if available
		if(typeof this.properties[property]!=="undefined"){
			propertyValue = this.properties[property]
		}else{
			// use Definition-level value for property if available
			if(typeof this.properties.definition!=="undefined" && typeof mediaDirectory[this.properties.definition]!=="undefined" && typeof mediaDirectory[this.properties.definition][property]!=="undefined"){
				propertyValue = mediaDirectory[this.properties.definition][property];
			}else{
				// use Global value for property if available
				if(typeof mediaDirectory[property]!=="undefined"){
					propertyValue = mediaDirectory[property];
				}else{
					// can't get property at all!
					eHA.log.create("can't load property: "+property,1);
				}
			}
		}
		return propertyValue;
	},
	/**
	 * adjusts the dimensions of the ".media_wrapper" element that should be wrapping
	 * the mediaObject.  The dimensions used are those that the eventual display will require
	 * so as to provide a smooth transition
	 * 
	 * @function
	 */
	adjustWrapper: function(){
		if($(this.properties.id).up(".media_wrapper")){
			eHA.log.create("adjusting wrapper for mediaObject "+this.properties.assetid, 3);
			// calculate proper height of embedded media, set as string
			var offsetHeight = 0;
			if(this[this.properties.definition].controlbarOffsetHeight){
				if(this[this.properties.definition].controlbarPosition && (this[this.properties.definition].controlbarPosition=="none" || this[this.properties.definition].controlbarPosition=="over") && this.properties.type!=="sound"){
					offsetHeight = 0;
				}else{
					offsetHeight = this[this.properties.definition].controlbarOffsetHeight;
				}
			}
			var thisHeight = (parseInt(this.properties.height,10)+parseInt(offsetHeight,10)).toString();
			// add dimensions to wrapper to provide a smoother loading experience
			// primary benefit is for use w/ thumbnails that are close to the size
			// of the embedded media
			$(this.properties.id).up(".media_wrapper").setStyle({
				'width': this.properties.width+"px",
				'height': thisHeight+"px"
			});
			// clear out wrapper of all but the clicked element
			// primary benefit is for use w/ text equivalents that fill wrapper
			// adjacent to clicked element
			$(this.properties.id).up(".media_wrapper").update($(this.properties.id));
		}
	},
	/**
	 * internal function that is called by initiate once data has been loaded and requiredProperties
	 * are available
	 * @function
	 * @private
	 */
	insert: function(){
		// for YouTube and Audio, play as a Video
		if(this.properties.definition=="YouTube" || this.properties.definition=="Audio"){
			this.properties.definition = "Video";
		}
		// at this point, the definition of the media is used to switch
		// to the correct [definition].insert function
		if(this.hasRequiredProperties()){
			
			var usePanels = this.getProperty("usePanels");
			
			if(typeof this.properties.portal === "undefined" || this.properties.portal!==true){
				if(usePanels){
					this.properties.panelid = "panel_media"; // this ID is reused
					this.properties.embed_id = "embed"+this.properties.assetid;
					if($(this.properties.embed_id)){
						eHA.log.create("this mediaObject ("+this.properties.assetid+") can't be inserted, it has already been inserted",1);
					}else{
						if(typeof this.panelItem==="undefined"){
							
							var metaHTML = new Element("div").addClassName("meta_data")
							
							if(this.properties.title){
								metaHTML.insert({bottom:new Element("h4").update(this.properties.title)});
							}
							if(this.properties.duration){
								metaHTML.insert({bottom:new Element("span").addClassName("duration").update(this.properties.duration)});
							}
							if(this.properties.date){
								metaHTML.insert({bottom:new Element("span").addClassName("date").update(this.properties.date)});
							}
							if(this.properties.description){
								metaHTML.insert({bottom:new Element("p").update(this.properties.description)});
							}
							
							var embedHTML = new Element("div",{id:this.properties.embed_id}).update("panel media");
							
							var mediaHTML = new Element("div").insert({bottom:embedHTML}).insert({bottom:metaHTML});
							
							this.panelItem = new panelObject({
								html:mediaHTML,
								panelid:this.properties.panelid,
								width: this.properties.width
							});
						}
						this.panelItem.insert();
					}
				}else{
					// only adjust wrapper if not using panel
					this.adjustWrapper();
				}
			}else{
				// this.properties.portal == true
				eHA.log.create("this mediaObject ("+this.properties.assetid+") won't have it's wrapper adjusted",3);
			}
			//eval("this."+this.properties.definition+".insert(this)");
			this[this.properties.definition].insert(this);
		}else{
			eHA.log.create("this mediaObject can't be inserted, it is lacking some required properties", 1);
		}
	},
	/**
	 * Outputs a JSON object version of this mediaObject for inspection and debugging
	 * 
	 * @param {boolean} useConsole if true, inspect uses FireBug's console.log() function to output the JSON 
	 * @function
	 */
	inspect: function(useConsole){
		if(useConsole){
			console.log("media"+this.properties.assetid+".properties = "+Object.toJSON(this.properties));
		}else{
			alert("media"+this.properties.assetid+".properties = "+Object.toJSON(this.properties));
		}
	},
	/**
	 * When called, this function seeks and removes the embedded mediaObject from the DOM
	 * should be used when leaving a page to clean up
	 * 
	 * @function
	 */
	remove: function(){
		if(typeof this.properties.embed_id !== "undefined" && $(this.properties.embed_id)){
			$(this.properties.embed_id).remove();
		}
		if(typeof this.properties.embed_id !== "undefined" && $(this.properties.embed_id+"controls")){
			$(this.properties.embed_id+"controls").remove();
		}
	},
	/**
	 * Video definition object
	 * @namespace
	 */
	Video: {
		/**
		 * @constant
		 * @property
		 */
		controlbarPosition: 'over',
		/**
		 * @constant
		 * @property
		 */
		controlbarOffsetHeight: 32, // this is dependent on the JW player's skin. usually 20.  24 for v5.1+
		/**
		 * Creates HTML controls that can be used by accessible technologies.  Takes advantage of the JW
		 * player's JS API.
		 * 
		 * @function
		 * @param {Object} thisMediaObject
		 */
		createHTMLcontrols: function(thisMediaObject){
			//var thisMediaObject = mediaDirectory.findByEl(obj);
			var playerControls = new Element("div",{"style":"position: absolute; left: -9999px;","id":thisMediaObject.properties.embed_id+"controls"});
			var controlsHeader = new Element("h5").update("Controls for Video: "+thisMediaObject.properties.title);
			var controlsOL = new Element("ol");
			var audiodescriptionLI = new Element("li").update("<a href=\"#\" onclick=\"javascript: mediaDirectory.state.audiodescription.toggle(); mediaDirectory.child_"+thisMediaObject.properties.assetid+".Video.insert(mediaDirectory.child_"+thisMediaObject.properties.assetid+"); return false;\"> toggle Audio Description and restart video</a>");
			var captionsLI = new Element("li").update("<a href=\"#\" onclick=\"javascript: mediaDirectory.state.captions.toggle(); mediaDirectory.child_"+thisMediaObject.properties.assetid+".Video.insert(mediaDirectory.child_"+thisMediaObject.properties.assetid+"); return false;\"> toggle Closed Captions and restart video</a>");
			var playLI = new Element("li").update("<a href=\"#\" onclick=\"javascript:$('"+thisMediaObject.properties.embed_id+"').sendEvent('PLAY'); return false;\">play/pause the video</a>");
			var muteLI = new Element("li").update("<a href=\"#\" onclick=\"javascript:$('"+thisMediaObject.properties.embed_id+"').sendEvent('MUTE'); return false;\">mute/unmute the video</a>");
			var stopLI = new Element("li").update("<a href=\"#\" onclick=\"javascript:$('"+thisMediaObject.properties.embed_id+"').sendEvent('STOP'); return false;\">rewind and stop the video</a>");
			controlsOL.insert({'bottom':audiodescriptionLI});
			controlsOL.insert({'bottom':captionsLI});
			controlsOL.insert({'bottom':playLI});
			controlsOL.insert({'bottom':muteLI});
			controlsOL.insert({'bottom':stopLI});
			playerControls.insert({'bottom':controlsHeader});
			playerControls.insert({'bottom':controlsOL});
			
			$(thisMediaObject.properties.embed_id).insert({'before':playerControls});
		},
		/**
		 * Evaluates the return object from SWFobject.  Prevents HTML controls from being created if e.success!==true
		 * 
		 * @param {Object} e SWFobject return object
		 */
		SWFcallback: function(e){
			if(e.success){
				this.Video.createHTMLcontrols(this);
			}else{
				// flash fail, insufficient version or none at all
				eHA.log.create(this.properties.assetid+": SWF object embed failed", 1);
				this.Flash.fail(this);
			}
		},
		insert: function(obj){
			var pluginString = "";
				pluginString += (typeof obj.properties.path_tt!=="undefined")?"captions-1,":"";
				pluginString += (typeof obj.properties.path_ad!="undefined")?"audiodescription-1,":"";
				pluginString = (pluginString.length>1)?pluginString.substring(0,pluginString.length-1):"";
			
			var thisHeight = "";
			if(this.controlbarPosition && (this.controlbarPosition=="over" || this.controlbarPosition=="none") && obj.properties.type!=="sound"){
				thisHeight = (parseInt(obj.properties.height,10)).toString();
			}else{
				thisHeight = (parseInt(obj.properties.height,10)+parseInt(this.controlbarOffsetHeight,10)).toString();
			}
			var controlbarPosition = (obj.properties.type==="sound")?"bottom":this.controlbarPosition;
			var flashvars = {
				'file': escape(unescape(obj.properties.href)), // unescape first for mimetype in blob URL
				'type': obj.properties.type,
				'provider': obj.properties.type, // use instead of 'type' for version 5+
				'autostart': mediaDirectory.state.autostart.value,
				'stretching': "uniform",
				'width': obj.properties.width,
				'height': thisHeight,
				'controlbar': controlbarPosition,
				/*
				'plugins': pluginString,
				*/
				'captions.file': escape(unescape(obj.properties.path_tt)),
				'captions.fontsize': 16,
				'captions.back': 'true',
				'captions.state': mediaDirectory.state.captions.value,
				
				'audiodescription.file': escape(unescape(obj.properties.path_ad)),
				'audiodescription.state': mediaDirectory.state.audiodescription.value
			};
			
			if(typeof obj.properties.path_tt!=="undefined" || typeof obj.properties.path_ad!="undefined"){
				flashvars.plugins = pluginString;
			}
			if(typeof obj.properties.path_tn!=="undefined"){
				flashvars.image = escape(unescape(obj.properties.path_tn));
			}

			/*
			if(typeof obj.properties.path_tt!=="undefined"){
				var captionsObject = {
					'file': escape(unescape(obj.properties.path_tt)),
					'fontsize': 16,
					'back': 'true',
					'state': mediaDirectory.state.captions.value
				};
				flashvars.captions = captionsObject.toQueryString;
			}
			
			if(typeof obj.properties.path_ad!="undefined"){
				flashvars.audiodescription = {
					'file': escape(unescape(obj.properties.path_ad)),
					'state': mediaDirectory.state.audiodescription.value
				};
			}
			
			*/
			
			if(eHA.JWskinpath){
				flashvars.skin = eHA.JWskinpath;
			}
			if(eHA.JWbackcolor){
				flashvars.backcolor = eHA.JWbackcolor;
			}
			if(eHA.JWfrontcolor){
				flashvars.frontcolor = eHA.JWfrontcolor;
			}
			if(eHA.JWlightcolor){
				flashvars.lightcolor = eHA.JWlightcolor;
			}
			if(eHA.JWscreencolor){
				flashvars.screencolor = eHA.JWscreencolor;
			}
			var params = {
				'wmode': 'transparent',
				'allowfullscreen': 'true'
			};
			
			var attributes = {
				'name': obj.properties.embed_id,
				'id': obj.properties.embed_id
			};
			eHA.log.create(obj.properties.assetid+": executing swfobject.embedSWF to embed_id="+obj.properties.embed_id, 3);
			swfobject.embedSWF(eHA.JWplayerpath, obj.properties.embed_id, obj.properties.width, thisHeight, eHA.requiredFlashVersion, false, flashvars, params, attributes, this.SWFcallback.bind(obj));
			return false;
		}
	},
	/**
	 * QuickTime definition object
	 * @namespace
	 */
	QuickTime: {
		controlbarOffsetHeight: 15,
		insert: function(obj){
			var thisHeight = (parseInt(obj.properties.height,10)+parseInt(this.controlbarOffsetHeight,10)).toString();
			
			var myQTObject = new QTObject(obj.properties.href, obj.properties.embed_id, obj.properties.width, thisHeight);
				//myQTObject.addParam("href", "bushuncensored.mov");
				//myQTObject.addParam("target", "myself");
				myQTObject.addParam("autostart", mediaDirectory.state.autostart.value);
				myQTObject.write(obj.properties.embed_id);
				
			return false;
		}
	},
	/**
	 * Flash definition object
	 * @namespace
	 */
	Flash: {
		SWFcallback: function(e){
			if(e.success){
				// nothing
			}else{
				// flash fail, insufficient version or none at all
				this.Flash.fail(this);
			}
		},
		fail: function(obj){
			var flashMessage = new Element("p").update("Please <a href='http://get.adobe.com/flashplayer/'>download the flash player</a> to view this content.");
			$(obj.properties.embed_id).insert({'after':flashMessage});
			return false;
		},
		insert: function(obj){
			var flashvars = {};
			if(typeof obj.properties.flashvars!=="undefined"){
				flashvars = obj.properties.flashvars.toQueryParams();
			}
			
			var params = {
				'wmode': 'opaque'
			};
			
			var attributes = {
				'name': obj.properties.embed_id,
				'id': obj.properties.embed_id
			};
			eHA.log.create(obj.properties.assetid+": executing swfobject.embedSWF to embed_id="+obj.properties.embed_id, 3);
			swfobject.embedSWF(obj.properties.href, obj.properties.embed_id, obj.properties.width, obj.properties.height, eHA.requiredFlashVersion, false, flashvars, params, attributes, this.SWFcallback.bind(obj));
			return false;
		}
	},
	/**
	 * Image definition object
	 * @namespace
	 */
	Image: {
		
	}
	
});
		
		
/**
 * object contains references to all {@link mediaObject} children<br />
 * objects and their data are accessible via assetid
 * 
 * @example 
 * var width = mediaDirectory.child_[assetid].properties.width;
 * mediaDirectory.child_[assetid].inspect(true);
 * mediaDirectory.child_[assetid].initiate();
 * 
 * @namespace
 * @author schopra
 * @property {boolean} usePanels default is FALSE
 * @property {boolean} useAJAX default is FALSE
 * @property {boolean} embedOnload default is FALSE
 * 
 */
var mediaDirectory = {
	defaultMediaObjectSelector: ".mediaObject",
	defaultPlaylistObjectSelector: ".playlistObject",
	/**
	 * states for mediaDirectory options
	 * @namespace
	 */
	state: {
		/**
		 * handles captions data and functions
		 * @namespace
		 * @property {String} value default is 'false'
		 */
		captions: {
			value: 'false',
			/**
			 * @function
			 */
			toggle: function(){
				if(mediaDirectory.state.captions.value==='false'){
					mediaDirectory.state.captions.value = 'true';
				}else{
					mediaDirectory.state.captions.value = 'false';
				}
			}
		},
		/**
		 * handles audiodescription data and functions
		 * @namespace
		 * @property {String} value default is 'false'
		 */
		audiodescription: {
			value: 'false',
			/**
			 * @function
			 */
			toggle: function(){
				if(mediaDirectory.state.audiodescription.value==='false'){
					mediaDirectory.state.audiodescription.value = 'true';
				}else{
					mediaDirectory.state.audiodescription.value = 'false';
				}
			}
		},
		/**
		 * @namespace
		 * @property {String} value default is 'true'
		 */
		autostart: {
			value: 'true'
		}
	},
	// definition-level values for usePanels etc.
	Flash:{
		usePanels: false,
		embedOnload: true
	},
	Audio:{
		usePanels: true,
		embedOnload: false
	},
	Video:{
		usePanels: true,
		embedOnload: false
	},
	YouTube:{
		usePanels: true,
		embedOnload: false
	},
	QuickTime:{
		usePanels: true,
		embedOnload: false
	},
	Image:{
		usePanels: true,
		embedOnload: false
	},
	usePanels: false,
	useAJAX: false,
	embedOnload: false,
	/**
	 * @function
	 * @param {String} assetid
	 * @returns {boolean} true if media exists as a child of the mediaDirectory
	 */
	mediaExists: function(assetid){
		if(typeof this["child_"+assetid]!=="undefined"){
			return true;
		}else{
			return false;
		}
	},
	/**
	 * @returns {Object} a reference to a mediaObject
	 * @function
	 * @param {Element} el HTML element that has assetid name-value pair in its class
	 */
	findByEl: function(el){
		var thisAssetID = eHA.loadValuefromClass(el, "assetid");
		if(typeof mediaDirectory["child_"+thisAssetID]!=="undefined"){
			return mediaDirectory["child_"+thisAssetID];
		}else{
			return false;
		}
	},
	/**
	 * @function
	 * @param {String} assetID
	 */
	addById: function(assetID){
		var newMO = new mediaObject({assetID:assetID});
		if(typeof this["child_"+newMO.properties.assetid]==="undefined"){
			if(newMO.properties.assetid){
				newMO.parent = this;
				this["child_"+newMO.properties.assetid] = newMO;
				return this["child_"+newMO.properties.assetid];
			}else{
				return false;
			}
		}else{
			// this mediaObject already exists
			return this["child_"+newMO.properties.assetid];
		}
	},
	/**
	 * If this mediaObject is not already in the mediaDirectory, create w/ pointer inside directory.  If media is Flash, executes 
	 * .initiate() to embed immediately.  Returns the new object or false if asset is not found
	 * @function
	 * @param {Element} el the mediaObject source element
	 * @returns {mediaObject} 
	 * @returns {boolean} false if assetid not found
	 */
	addByEl: function(el){
		var newMO = new mediaObject({element:el});
		if(typeof this["child_"+newMO.properties.assetid]==="undefined"){
			if(newMO.properties.assetid){
				newMO.parent = this;
				this["child_"+newMO.properties.assetid] = newMO;
				// embed Flash media immediately, regardless of mediaDirectory.embedOnload value
				
				var embedOnload = newMO.getProperty("embedOnload");
				
				if(embedOnload){
					newMO.initiate();
				}else{
					$(el).observe("click",function(event){
						event.stop();
						newMO.initiate();
					});
				}
				//return eval("mediaDirectory.child_"+newMO.properties.assetid);
				return this["child_"+newMO.properties.assetid];
			}else{
				return false;
			}
		}else{
			// this mediaObject already exists
			return this["child_"+newMO.properties.assetid];
		}
	},
	addPlaylistByEl: function(el){
		var newPO = new playlistObject({element:el});
		if(typeof newPO.properties.assetid!=="undefined" && typeof this["child_"+newPO.properties.assetid]==="undefined"){
			newPO.parent = this;
			this["child_"+newPO.properties.assetid] = newPO;
			// embed playlists immediately if usePanels is false
			if(mediaDirectory.embedOnload){
				newPO.initiate();
			}else{
				// must observe click
				newPO.properties.el.observe("click",function(event){
					event.stop();
					newPO.initiate();
				}).setStyle({
					cursor:'pointer'
				});
			}
			return this["child_"+newPO.properties.assetid];
		}else{
			// playlist already exists or assetid is not available
			return false;
		}
	},
	/**
	 * Outputs an alert of Object.toJSON(this) -- the mediaDirectory
	 * @function
	 * @param {Boolean} useConsole if true, will output to FireBug's Console instead
	 */
	inspect: function(useConsole){
		if(useConsole){
			console.log("mediaDirectory = "+Object.toJSON(this));
		}else{
			alert("mediaDirectory = "+Object.toJSON(this));
		}
	},
	/**
	 * @function
	 * @returns {Array} Array of child keys for {@link mediaDirectory}
	 */
	getChildKeys: function(){
		var returnArray = []; 
		for(var i=0;i<Object.keys(this).length;i++){
			if(Object.keys(this)[i].indexOf("child_")!=-1){
				returnArray.push(Object.keys(this)[i]);
			}
		}
		return returnArray;
	},
	/**
	 * Uses selector to find mediaObjects (default is .mediaObject).  Initiates construction of panels, sets useAJAX and usePanels
	 * booleans from page.  Sets autostart value based on embedOnload boolean.  Creates mediaObject per element found, using this.addByEl().
	 * Fires "media:loaded" event once complete.
	 *  
	 * @function
	 * @param {String} mo_selector a CSS selector
	 * @param {String} po_selector a CSS selector
	 */
	assignMediaEvents: function(mo_selector,po_selector){
		try{
			if(typeof eHA.useAJAX !=="undefined"){
				this.useAJAX = eHA.useAJAX;
			}
			if(typeof eHA.usePanels!=="undefined"){
				this.usePanels = eHA.usePanels;
			}
			var MOselector = this.defaultMediaObjectSelector;
			if(typeof selector!=="undefined"){
				MOselector = mo_selector;
			}
			var POselector = this.defaultPlaylistObjectSelector;
			if(typeof selector!=="undefined"){
				POselector = po_selector;
			}
			if(typeof panels!=="undefined" && typeof panels.construct!=="undefined"){
				// must always construct panels if available
				panels.construct();
			}
			if(mediaDirectory.embedOnload){
				mediaDirectory.state.autostart.value = 'false';
			}
			if($$(MOselector)[0]){
				$$(MOselector).each(function(element){
					mediaDirectory.addByEl(element);
				});
				document.fire("media:loaded");
			}
			if($$(POselector)[0]){
				$$(POselector).each(function(element){
					mediaDirectory.addPlaylistByEl(element);
				});
				document.fire("playlists:loaded");
			}
		}
		catch(error){alert(error.message)}
		
	},
	/**
	 * removes any embedded media and associated panels (usually 
	 * tied to event "window.beforeunload")
	 * 
	 * @function
	 */
	removeAll: function(){
		eHA.log.create("removing all media", 3);
		for(var i=0;i<mediaDirectory.getChildKeys().length;i++){
			mediaDirectory[mediaDirectory.getChildKeys()[i]].remove();
		}

	}
};

var playlistObject = Class.create(
/** 
 * @lends playlistObject.prototype
 * 
 */
{
	/**
	 * 
	 * @author schopra
	 * @constructs
	 */
	initialize: function(obj){
		 if(typeof obj !=="undefined"){
			 if(typeof obj.element!=="undefined"){
				 this.properties = eHA.elementToObjectLiteral(obj.element);
				 this.properties.embed_id = this.properties.id+"";
				 this.properties.complete = false;
				 this.properties.el = $(obj.element);
				 if(this.properties.definition==="Image_Playlist"){
					 this.properties.playerpath = eHA.JWImageRotatorPath;
				 }
				 if(this.properties.definition==="Video_Playlist"){
					 this.properties.playerpath = eHA.JWplayerpath;
				 }
				 return this;
			 }else{
				 if(typeof obj.assetID!=="undefined"){
					 // must assume assettype = "Module_C" for AJAX to work
					 this.properties = {assetid: obj.assetID,assettype:"Module_C",complete:false};
					 return this;
				 }else{
					 return false;
				 }
			 }
		 }else{
			 return false;
		 }
 	},
 	initiate: function(){

		if(this.properties.complete){
			if(!this.properties.complete && !mediaDirectory.useAJAX){
				eHA.log.create("can't load playlist without AJAX while not complete",2);
			}else{
				this.insert();
			}
		}else{
			this.loadData("mediaDirectory['child_"+this.properties.assetid+"'].insert()");
		}
 	},
 	insert: function(){
 		if(mediaDirectory.usePanels){
 			panels.appear();
			this.properties.panelid = "panel_media"; // this ID is reused
			this.properties.embed_id = "embed"+this.properties.assetid;
			if($(this.properties.embed_id)){
				eHA.log.create("this mediaObject ("+this.properties.assetid+") can't be inserted, it has already been inserted",1);
			}else{
				if(typeof this.panelItem==="undefined"){
					var metaHTML = new Element("div").addClassName("meta_data")
					
					if(this.properties.title){
						metaHTML.insert({bottom:new Element("h4").update(this.properties.title)});
					}
					if(this.properties.duration){
						metaHTML.insert({bottom:new Element("span").addClassName("duration").update(this.properties.duration)});
					}
					if(this.properties.date){
						metaHTML.insert({bottom:new Element("span").addClassName("date").update(this.properties.date)});
					}
					if(this.properties.description){
						metaHTML.insert({bottom:new Element("p").update(this.properties.description)});
					}
					
					var embedHTML = new Element("div",{id:this.properties.embed_id}).update("panel media");
					
					var mediaHTML = new Element("div").insert({bottom:embedHTML}).insert({bottom:metaHTML});
					
					
					this.panelItem = new panelObject({
						html:mediaHTML,
						panelid:this.properties.panelid,
						width: this.properties.width
					});
				}
				this.panelItem.insert();
			}
		}else{
			// only adjust wrapper if not using panel
			this.adjustWrapper();
		}
 		this[this.properties.definition].insert(this);
 	},
 	adjustWrapper: function(){
		// add dimensions to wrapper to provide a smoother loading experience
		// primary benefit is for use w/ thumbnails that are close to the size
		// of the embedded media
		var adjustmentDuration = 0.3;
		var wrapper = $(this.properties.id).up(".module_wrapper");
		var wrapperDimensions = wrapper.getDimensions();
		
		wrapper.childElements().invoke("fade",{duration:adjustmentDuration});
		
		// set dimensions explicitly so that morph isn't jerky
		$(this.properties.id).up(".module_wrapper").setStyle({
			'width':wrapperDimensions.width+"px",
			'height':wrapperDimensions.height+"px",
			'overflow':'hidden'
		}).morph({
			'width': this.properties.width+"px",
			'height': this.properties.height+"px"
		},{
			afterFinish: function(){
				// make sure to keep the target element visible 
				$(this.properties.el).show();
			}.bind(this),
			duration:adjustmentDuration
		});
	},
 	Image_Playlist: {
	 	insert: function(obj){
	 		try{
	 			
	 			var flashvars = {
	 					height: 		obj.properties.height,
	 					width: 			obj.properties.width,
	 					file: 			escape(unescape(obj.properties.file)),
	 					showicons: 		obj.properties.showicons,
	 					shownavigation: obj.properties.shownavigation,
	 					transition: 	obj.properties.transition,
	 					repeat: 		obj.properties.repeat,
	 					rotatetime: 	obj.properties.rotatetime,
	 					shuffle: 		obj.properties.shuffle,
	 					overstretch: 	true,
	 					usefullscreen: 	true,
	 					enablejs:		true
	 			};
	 			
	 			var params = {
	 					wmode: 			'transparent',
	 					allowfullscreen:true
	 			};
	 			
	 			var attributes = {
	 					name: 			obj.properties.embed_id,
	 					id: 			obj.properties.embed_id
	 			};
	 			
	 			if(typeof obj.properties.audio!=="undefined"){
	 				flashvars.audio = escape(unescape(obj.properties.audio));
	 			}
	 			if(typeof obj.properties.logo!=="undefined"){
	 				flashvars.logo = escape(unescape(obj.properties.logo));
	 			}
	
	 			if(eHA.JWbackcolor){
	 				flashvars.backcolor = eHA.JWbackcolor;
	 			}
	 			if(eHA.JWfrontcolor){
	 				flashvars.frontcolor = eHA.JWfrontcolor;
	 			}
	 			if(eHA.JWlightcolor){
	 				flashvars.lightcolor = eHA.JWlightcolor;
	 			}
	 			if(eHA.JWscreencolor){
	 				flashvars.screencolor = eHA.JWscreencolor;
	 			}
	 			
	 			eHA.log.create(obj.properties.assetid+": executing swfobject.embedSWF to embed_id="+obj.properties.embed_id, 3);
	 			
	 			swfobject.embedSWF(obj.properties.playerpath, obj.properties.embed_id, obj.properties.width, obj.properties.height, eHA.requiredFlashVersion, false, flashvars, params, attributes, obj.SWFcallback);
	 		}catch(err){
	 			eHA.log.create(obj.properties.assetid+":"+err.name+" - "+err.message, 1);
	 		}
	 	}
 	},
 	Video_Playlist: {
 		insert: function(obj){
	 		try{
	 			
	 			var flashvars = {
	 					height: 			obj.properties.height,
	 					width: 				obj.properties.width,
	 					playlistfile:		escape(unescape(obj.properties.file)),
	 					playlist: 			obj.properties.playlist,
	 					playlistsize:		obj.properties.playlistsize,
	 					repeat: 			obj.properties.repeat,
	 					shuffle: 			obj.properties.shuffle,
	 					autostart:			true,
	 					icons:				obj.properties.icons,
	 					'playlist.thumbs': 	obj.properties.playlistthumbs
	 			};
	 			
	 			// note: the Modieus skin (used by UM) doesn't properly
	 			// deal with thumbnails in the playlist.  try default
	 			// skin for a better idea of what should happen
	 			
	 			var params = {
	 					wmode: 			'transparent',
	 					allowfullscreen:true
	 			};
	 			
	 			var attributes = {
	 					name: 			obj.properties.embed_id,
	 					id: 			obj.properties.embed_id
	 			};
	 			
	 			if(typeof obj.properties.audio!=="undefined"){
	 				flashvars.audio = escape(unescape(obj.properties.audio));
	 			}
	 			if(typeof obj.properties.logo!=="undefined"){
	 				flashvars.logo = escape(unescape(obj.properties.logo));
	 			}
				if(eHA.JWskinpath){
					flashvars.skin = eHA.JWskinpath;
				}
	 			if(eHA.JWbackcolor){
	 				flashvars.backcolor = eHA.JWbackcolor;
	 			}
	 			if(eHA.JWfrontcolor){
	 				flashvars.frontcolor = eHA.JWfrontcolor;
	 			}
	 			if(eHA.JWlightcolor){
	 				flashvars.lightcolor = eHA.JWlightcolor;
	 			}
	 			if(eHA.JWscreencolor){
	 				flashvars.screencolor = eHA.JWscreencolor;
	 			}
	 			
	 			eHA.log.create(obj.properties.assetid+": executing swfobject.embedSWF to embed_id="+obj.properties.embed_id, 3);
	 			
	 			swfobject.embedSWF(obj.properties.playerpath, obj.properties.embed_id, obj.properties.width, obj.properties.height, eHA.requiredFlashVersion, false, flashvars, params, attributes, obj.SWFcallback);
	 		}catch(err){
	 			eHA.log.create(obj.properties.assetid+":"+err.name+" - "+err.message, 1);
	 		}
 		}
 	},
	SWFcallback: function(e){
		if(e.success){
			//this.Video.createHTMLcontrols(this);
		}else{
			// flash fail, insufficient version or none at all
			eHA.log.create(this.properties.assetid+": SWF object embed failed", 1);
			//this.Flash.fail(this);
		}
	},
 	loadData: function(callback){
 		
		var URL = "/cs/Satellite";
		var pagename = eHA.Site+"_default_Wrapper";
		var childpagename = eHA.Site+"/"+this.properties.assettype+"/"+eHA.Site+"/"+this.properties.definition+"/json";
		if(eHA.Site==="demo"){
			URL = "Satellite.php";
			pagename="JSON";
		}
		var parameters = {
		  pagename: pagename,
		  childpagename: childpagename,
		  site: eHA.Site,
		  c: this.properties.assettype,
		  cid: this.properties.assetid
		};
		try{
			new Ajax.Request(URL,
				{
					method:'get',
					asynchronous: false,  // shouldn't this be true?
					parameters: parameters,
					onCreate: function(){
						eHA.log.create(parameters.cid+": AJAX request for JSON created", 3);
					},
					onSuccess: function(transport){
						eHA.log.create(parameters.cid+": AJAX request for JSON succeeded", 3);
					},
					onComplete: function(transport){
						// add transport.responseText to this.properties
						eHA.log.create(parameters.cid+": AJAX request for JSON completed", 3);
						if(transport.responseText){
							eHA.log.create(parameters.cid+": attempting to evaluate JSON and add to playlistObject", 3);
							try{
								var metaData = transport.responseText.evalJSON(true);
								Object.extend(mediaDirectory["child_"+metaData.assetid].properties,metaData);
								mediaDirectory["child_"+metaData.assetid].properties.complete = true;
								eHA.log.create(parameters.cid+": executing callback:"+callback, 3);
								eval(callback);
							}catch(err){
								eHA.log.create(parameters.cid+":"+err.name+" - "+err.message, 1);
							}
						}else{
							eHA.log.create(parameters.cid+": problem with transport.responseText onComplete", 1);
						}
					},
					onFailure: function(){
						eHA.log.create(parameters.cid+": AJAX request for JSON resulted in failure", 1);
					}
				});
		}catch(err){
			eHA.log.create(parameters.cid+":"+err.name+" - "+err.message, 1);
		}
 	}
});




Event.observe(window,"beforeunload", mediaDirectory.removeAll);
