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 = "includes/video.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);
									}
								}
								if(mediaDirectory["child_"+metaData.assetid].properties.type==="video2"){
								mediaDirectory["child_"+metaData.assetid].properties.type = "video";
								}
								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(){
		// hardcoding for flash to never use panels
		if(mediaDirectory.usePanels && this.properties.definition!="Flash"){
			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;
	},
	/**
	 * 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
	 */
	adjust_wrapper: 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=="Video2"){
			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()){
			// hardcoding for flash to never use panels
			if(typeof this.properties.portal === "undefined" || this.properties.portal!==true){
				if(mediaDirectory.usePanels && this.properties.definition!="Flash"){
					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"){
							this.panelItem = new panelObject(this);
						}
						this.panelItem.insert();
					}
				}else{
					// only adjust wrapper if not using panel
					this.adjust_wrapper();
				}
			}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
	 * 
	 * @field
	 * @private
	 */
	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
			};
			
			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
	 * 
	 * @field
	 * @private
	 */
	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
	 * 
	 * @field
	 * @private
	 */
	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
			};
			
			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
	 * 
	 * @field
	 * @private
	 */
	Image: {
		
	}
	
});
		
		
/**
 * object contains references to all mediaObject children
 * 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
 * @property {String} state.captions.value default is 'false' This is used by JW player
 * 
 * 
 */
var mediaDirectory = {
	defaultMediaObjectSelector: ".mediaObject",
	state: {
		captions: {
			value: 'false',
			toggle: function(){
				if(mediaDirectory.state.captions.value==='false'){
					mediaDirectory.state.captions.value = 'true';
				}else{
					mediaDirectory.state.captions.value = 'false';
				}
			}
		},
		audiodescription: {
			value: 'false',
			toggle: function(){
				if(mediaDirectory.state.audiodescription.value==='false'){
					mediaDirectory.state.audiodescription.value = 'true';
				}else{
					mediaDirectory.state.audiodescription.value = 'false';
				}
			}
		},
		autostart: {
			value: 'true'
		}
	},
	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;
		}
	},
	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];
		}
	},
	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
				if((typeof newMO.properties.definition !== "undefined" && newMO.properties.definition=="Flash" ) || mediaDirectory.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];
		}
	},
	inspect: function(useConsole){
		if(useConsole){
			console.log("mediaDirectory = "+Object.toJSON(this));
		}else{
			alert("mediaDirectory = "+Object.toJSON(this));
		}
	},
	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;
	},
	assignMediaEvents: function(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 = selector;
		}
		
		if(mediaDirectory.usePanels){
			panels.construct();
		}
		if(mediaDirectory.embedOnload){
			mediaDirectory.state.autostart.value = 'false';
		}
		if($$(MOselector)[0]){
			$$(MOselector).each(function(element){
				mediaDirectory.addByEl(element);
			});
			document.fire("media: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();
		}

	}
};


//document.observe("dom:loaded", function(){alert('dom loaded');mediaDirectory.assignMediaEvents();});
Event.observe(window,"beforeunload", mediaDirectory.removeAll);
