/**
 * @author rrobinson
 */

/**
 * This function implements jsTrace ...
 * @param {string} msg
 */
function trace( msg ){
	if( typeof( jsTrace ) != 'undefined' ){
		jsTrace.send( msg );
	}
}

var jsHDVideo = (function(){
	// -------------------------------------------------------
	// --------------- PRIVATE PROPERTIES --------------------
	// -- while these properties are not available after the
	// -- the function returns they are still available to 
	// -- each of the methods in the object returned because
	// -- lexical scoping in javascript
	// -------------------------------------------------------
	
	// ------------------- CONSTANTS -----------------------------
	var CONST_PLAYERDIV = "playerDiv";
	var CONST_IFRAME_ID = "hdfndngoIframe";
	var CONST_HDPLAYER_PAGENAME = "HDFandangoPlayer.aspx";
	// -----------------------------------------------------------
	
	var _isPlayerLoaded = false;
	var _isMediaComplete = true;
	var _clipData = null;
	var Count = 0;
	var videoTimer = null;
	var countTimerInterval = 0;
	var _moveId = "";
	var _movieTitle = "";
	var _tweetsCache = {};
	
	/**
	 * This function will invoke the function passed as the method parameter as a member of the
	 * object passed as the scope parameter and pass the parameter arg to the invoked function.
	 *
	 * @param {Object} scope
	 * @param {function} method
	 * @param {*} arg
	 */
	var delegate = function(scope, method, arg)
	{
		return function(){
			return method.call(scope, arg);
		};
	};
		
	/**
	 * This function simply dumps a javascript object as a string
	 *
	 * @param {string} header
	 * @param {Object} obj
	 * @param {number} level
	 */
	var dumpObj = function (obj, depth){
		var indent = '';
		var level = 0;
		if (depth)
		{
			level = depth;
			for(var i=0; i < level; i++)
			{
				indent += "\t";
			}
		}
		
		var text = "{";
		for(var prop in obj)
		{
			text += "\n" + indent + prop + ":";
			if ( typeof obj[prop] == 'object')
			{
				text += dumpObj(obj[prop], level + 1);
			}
			else
			{
				text += obj[prop] + ",";
			}
		}
		text += indent + "}\n";
		
		return text;
	};

	/**
	 * This is essentially a private function that is used internally by
	 * jsHDVideo.attachShare and jsHDVideo.attachTwitterDialog. It will
	 * return an object that can be will be used as the 1st parameter of 
	 * SHARETHIS.addEntry(parameter1, parameter2).
	 *
	 * @param (Object) obj this object contains the hd video fields for
	 *        for the item clicked on the hdmovietrailers page
	 */
	var getShareThisParameter = function(obj)
	{
		var parm = {}; // initialize an empty object
		
		if (!obj.movieTitle || obj.movieTitle == "")
		{
			var mvtitle = obj.title;
			if (obj.title.indexOf(':') != -1)
			{
				// keep characters on left of :
				var fields = obj.title.split(':');
				mvtitle = fields[0];
			}
			parm.title = "Watch the " + mvtitle + " trailer on #Fandango";
		}
		else
		{
			parm.title = "Watch the " + obj.movieTitle + " trailer on #Fandango";	// add the title property
		}
		
		parm.url = obj.trailerPage;		// add the trailer page url
		
		// format a description
		var desc = "";
		if (obj.description && obj.description != "")
		{
			desc = obj.description.replace("\"", "&quot;");
			desc.replace("\'", "&#39;");
			desc.replace("\n", " ");
		}
		parm.summary = desc;	// add the description to the summary property
		
		// encode the thumbnail url
		var imglink = "";
		if (obj.thumbnailURL && obj.thumbnailURL != "")
		{
			imglink = encodeURI(obj.thumbnailURL);
		}
		parm.icon = imglink;	// add thumbnail url to icon property
		
		return parm; // return parm to be used as 1st paramter of SHARETHIS.addEntry()
	};
	
	// -------------------------------------------------------
	// The following statement simply returns an object containing
	// the methods for jsHDVideo.
	// -------------------------------------------------------
	return {	
		/**
		 * several functions in hdtrailers.js use this field to extract & construct a response object from the
		 * 'rel' attribute of an anchor tag on the HD Galleries page.
		 *
		 * TT 8931 - rrobinson - added fields for description and thumbnailURL
		 * 
		 * TT 8953 - 11/17/2009 - rrobinson - added new field "rating" before the optional fields
		 *
		 * TT 8771 - 9/10/2009 - rrobinson - added two optional fields: optContentCategory and optPageName to pass the
		 * WSS content category and page name values to the HDFandangoPlayer.aspx when a play is triggered
		 * by the HDFandangoPuppetTrailers.aspx page.
		 *
		 * NOTE: since optContentCategory and optPageName are optional they should always be at the end of the
		 * array; only optional fields should be appended after them.
		 **/
		hdVideoFields : ["gotoMovie", "guid", "movieCategory", "movieTitle", "movieID", "rating", "description", "thumbnailURL", "optContentCategory", "optPageName"],
		
		initialize : function()
		{
			//_isPlayerLoaded = false;
			this._isMediaComplete = true;
			this._clipData = null;
			this.Count = 0;
			this.videoTimer = null;
			this.countTimerInterval = 0;
			
			if (tpController)
			{
				tpController.register(delegate(this, this.playerLoaded));
			}
		},
		
		getHostUrl : function()
		{
			var protocol = window.location.protocol + "//";
			var host = window.location.host;
			
			if ( (host.toLowerCase()).indexOf(".com") == -1 )
			{
				host += "/fandango";
			}
			
			return protocol + host;
		},
		
		/**
		 * This method returns the value of _isPlayerLoaded ...
		 */
		isPlayerLoaded: function ()
		{
			return _isPlayerLoaded;
		},
		
		/**
		 * This method stops the videoTimer
		 */
		stopVideoTimer : function()
		{
			if (videoTimer)
			{
				clearInterval(videoTimer);
				videoTimer = null;
			}
		},
	
		play : function(obj)
		{
			trace("called play(): dumping:");
			trace(dumpObj(obj));
			
			this.startPlayer(obj);
			
			// By the time this point is reached the 'obj' object has been augmented with a title from
			// thePlatform for trailer about to be played. The following call will cause an _hbPageView()
			// call to track the playing of this trailer.
			// *** TT #8291 - the following call is no longer needed
			// HDFandangoPlayer.aspx initializes the hbx.pn and hbx.mlc in the FanCon:AnalyticsControl
			//this.wssPageView(obj);
		},
		
		wssPageView: function(obj)
		{
			var temp = obj.movieCategory.replace("MOVIE ", "");
			var result = temp + "_";
			var pattern = /\s/g;	
			
			if (obj.movieTitle)
			{
				temp = obj.movieTitle.replace(pattern, "+");
				result += temp + "_";
				
				if (obj.movieID)
				{
					result += obj.movieID;
				}
				else
				{
					result += obj.guid;
				}
			}
			else
			{
				temp = obj.title.replace(pattern, "+");
				result += temp + "_";
				
				if (obj.movieID)
				{
					result += obj.movieID;
				}
				else
				{
					result += obj.guid;
				}
			}
			
			result = result.replace(pattern, "+");
			//trace("WSS Reporting: VI/HDPlayed ==>" + result);
			_hbPageView(result, "VI/HDPlayed");
		},
		
		endPlayback : function()
		{
			trace("endPlayback() called");
			
			if (!this._isMediaComplete && typeof (tpController) != "undefined")
			{
				tpController.stop();
				tpController.dispatchEvent("OnMediaEnd", _clipData, tpController.ID, "javascript");
			}
			
			//_isPlayerLoaded = false;
			
			// remove the iframe
			var playerDiv = document.getElementById(CONST_PLAYERDIV); // get the iframe parent
			var iframe = document.getElementById(CONST_IFRAME_ID);
			if (playerDiv)
			{
				if (iframe)
				{
					// remove the current iframe
					playerDiv.removeChild(iframe);
					iframe = null;
				}
			}
			
		},
		
		/**
		 * Every quarter second this method is called to check if the _isPlayerLoaded variable is true.
		 * If it is true then it stops the video timer and calls tpController.setReleaseURL() to send
		 * the currently selected player url to the flvPlayer.
		 * 
		 * @param {Object} hdURL
		 */
		sendReleaseURL : function(hdURL)
		{
			trace("isPlayerLoaded = " + this.isPlayerLoaded());
			if (this.isPlayerLoaded())
			{
				this.stopVideoTimer();
				tpController.setReleaseURL(hdURL);
			}
			else if (countTimerInterval >= 30)
			{
				this.stopVideoTimer();
				trace("HD player not ready! Closing player window.");
				return;
			}
			countTimerInterval++;
		},
					
		/**
		 * This method is provided as a callback function to registered with tpController.registerFunction().
		 * If called it will set the variable _isPlayerLoaded to true;
		 */
		playerLoaded : function()
		{
			this._isPlayerLoaded = true;
			this.configureListeners();
			trace("The player has been loaded!");
		},
		
		/**
		 * This method establishes event listeners for several events dispatched by thePlatform's controls
		 */
		configureListeners : function()
		{
			trace("Called jsHDVideo.configureListeners");
			if (typeof (tpController) != "undefined")
			{
				tpController.addEventListener("OnPlayerLoaded", "jsHDVideo.jsEventHandler");
				tpController.addEventListener("OnClipInfoLoaded", "jsHDVideo.jsEventHandler");
				tpController.addEventListener("OnJavascriptLoaded", "jsHDVideo.jsEventHandler");
				tpController.addEventListener("OnMute", "jsHDVideo.jsEventHandler");
				tpController.addEventListener("OnSetReleaseUrl", "jsHDVideo.jsEventHandler");
				tpController.addEventListener("OnSetVolume", "DVIDEO.jsEventHandler");
				tpController.addEventListener("OnShowFullScreen", "jsHDVideo.jsEventHandler");
				tpController.addEventListener("OnReleaseStart", "jsHDVideo.jsEventHandler");
				tpController.addEventListener("OnReleaseEnd", "jsHDVideo.jsEventHandler");
				tpController.addEventListener("OnMediaLoadStart", "jsHDVideo.jsEventHandler");
				tpController.addEventListener("OnMediaLoading", "jsHDVideo.jsEventHandler");
				tpController.addEventListener("OnMediaStart", "jsHDVideo.jsEventHandler");
				tpController.addEventListener("OnMediaPlaying", "jsHDVideo.jsEventHandler");
				tpController.addEventListener("OnMediaEnd", "jsHDVideo.jsEventHandler");
				tpController.addEventListener("OnMediaComplete", "jsHDVideo.jsEventHandler");
				tpController.addEventListener("OnMediaBuffer", "jsHDVideo.jsEventHandler");
				tpController.addEventListener("OnMediaPlay", "jsHDVideo.jsEventHandler");
				tpController.addEventListener("OnMediaPause", "jsHDVideo.jsEventHandler");
				tpController.addEventListener("OnMediaUnpause", "jsHDVideo.jsEventHandler");
				tpController.addEventListener("OnMediaSeek", "jsHDVideo.jsEventHandler");
				// tpController.addEventListener("", "jsHDVideo.jsEventHandler");
			}
			trace("tpController Event Listeners configured!");
		},
		
		removeListeners : function()
		{
			trace("Called jsHDVideo.removeListeners");
			if (typeof (tpController) != "undefined")
			{
				tpController.removeEventListener("OnPlayerLoaded", "jsHDVideo.jsEventHandler");
				tpController.removeEventListener("OnClipInfoLoaded", "jsHDVideo.jsEventHandler");
				tpController.removeEventListener("OnJavascriptLoaded", "jsHDVideo.jsEventHandler");
				tpController.removeEventListener("OnMute", "jsHDVideo.jsEventHandler");
				tpController.removeEventListener("OnSetReleaseUrl", "jsHDVideo.jsEventHandler");
				tpController.removeEventListener("OnSetVolume", "jsHDVideo.jsEventHandler");
				tpController.removeEventListener("OnShowFullScreen", "jsHDVideo.jsEventHandler");
				tpController.removeEventListener("OnReleaseStart", "jsHDVideo.jsEventHandler");
				tpController.removeEventListener("OnReleaseEnd", "jsHDVideo.jsEventHandler");
				tpController.removeEventListener("OnMediaLoadStart", "jsHDVideo.jsEventHandler");
				tpController.removeEventListener("OnMediaLoading", "jsHDVideo.jsEventHandler");
				tpController.removeEventListener("OnMediaStart", "jsHDVideo.jsEventHandler");
				tpController.removeEventListener("OnMediaPlaying", "jsHDVideo.jsEventHandler");
				tpController.removeEventListener("OnMediaEnd", "jsHDVideo.jsEventHandler");
				tpController.removeEventListener("OnMediaComplete", "jsHDVideo.jsEventHandler");
				tpController.removeEventListener("OnMediaBuffer", "jsHDVideo.jsEventHandler");
				tpController.removeEventListener("OnMediaPlay", "jsHDVideo.jsEventHandler");
				tpController.removeEventListener("OnMediaPause", "jsHDVideo.jsEventHandler");
				tpController.removeEventListener("OnMediaUnpause", "jsHDVideo.jsEventHandler");
				tpController.removeEventListener("OnMediaSeek", "jsHDVideo.jsEventHandler");
				// tpController.removeEventListener("", "jsHDVideo.jsEventHandler");
			}
			trace("tpController Event Listeners removed!");
		},
		
		/**
		 * This method is the event listener for events dispatched from thePlatform's controls
		 * 
		 * @param {Object} evt	thePlatform's javascript Event object
		 */
		jsEventHandler : function(evt)
		{	// parameter is Event from utils.js (from thePlatform's PDK)
			//trace("jsEventHandler() handling event.type = " + e.type);
			switch(evt.type)
			{
				case "OnPlayerLoaded":
					trace("jsEventHandler() handling event.type = " + evt.type);
					if (!this._isPlayerLoaded) 
					{
						this._isPlayerLoaded = true;
					}
					break;
				case "OnClipInfoLoaded":
					break;
				case "OnJavascriptLoaded":
					trace("jsEventHandler() handling event.type = " + evt.type);
					break;
				case "OnMute":
					// WSS Reporting:
					_hbLink("VIDHD_Player", "VIDHD_Player_Volume");
					break;
				case "OnSetReleaseUrl":
					trace("jsEventHandler() handling event.type = " + evt.type);
					break;
				case "OnSetVolume":
					// WSS Reporting:
					_hbLink("VIDHD_Player", "VIDHD_Player_Volume");
					break;
				case "OnShowFullScreen":
					// WSS Reporting: (Expand)
					_hbLink("VIDHD_Player", "VIDHD_Player_Expand");
					break;
				case "OnReleaseStart":
					trace("jsEventHandler() handling event.type = " + evt.type);
					_clipData = null;
					break;
				case "OnReleaseEnd":
					trace("jsEventHandler() handling event.type = " + evt.type);
					break;
				case "OnMediaLoadStart":
					trace("jsEventHandler() handling event.type = " + evt.type);
					break;
				case "OnMediaLoading":
					break;
				case "OnMediaStart":
					trace("jsEventHandler() handling event.type = " + evt.type);
					this._isMediaComplete = false;
					this._clipData = evt.data;
					//trace("_clipData : " + dumpObj(_clipData));
					break;
				case "OnMediaPlaying":
					//trace("jsEventHandler() handling event.type = " + evt.type);
					break;
				case "OnMediaEnd":
					trace("jsEventHandler() handling event.type = " + evt.type);
					break;
				case "OnMediaComplete":
					this._isMediaComplete = true;
					break;
				case "OnMediaBuffer":
					break;
				case "OnMediaPlay":
					trace("jsEventHandler() handling event.type = " + evt.type);
					//_hbLink("VIDHD_Player", "");
					break;
				case "OnMediaPause":
					// WSS Reporting:
					_hbLink("VIDHD_Player", "VIDHD_Player_Pause");
					break;
				case "OnMediaUnpause":
					// WSS Reporting:
					_hbLink("VIDHD_Player", "VIDHD_Player_Play");
					break;
				case "OnMediaSeek":
					// WSS Reporting:
					_hbLink("VIDHD_Player", "VIDHD_Player_Scrub");
					break;
			}
		}, // closing jsEventHandler
		
		/**
		 * This method starts the player for the IE browsers. It first extracts the protocol and domain from the
		 * from the current page location and build a new url referencing the page to be installed in the iframe and
		 * provides a parameter indicating the releaseUrl of the movie requested. Finally, it builds the iframe.
		 **/
		startPlayer: function (obj) {
			var pagename = CONST_HDPLAYER_PAGENAME;
			
			var playerUrl = this.getHostUrl() + "/" + pagename + "?src=" + obj.guid + "&r=" + obj.rating;
			
			if (obj.optContentCategory && obj.optContentCategory != '')
			{
				playerUrl += "&mlc=" + obj.optContentCategory;
			}

			if (obj.optPageName && obj.optPageName != '')
			{
				playerUrl += "&pn=" + obj.optPageName;
			}
			
			trace("startPlayer(): playerUrl = " + playerUrl);
			
			this.createIframe(CONST_PLAYERDIV, CONST_IFRAME_ID, playerUrl);
			
			this.attachTwitterDialog("tweetHeader", obj);
			this.attachTwitterDialog("share-tweet", obj);
			this.attachShare("share-this", obj);
		},
		
		/**
		 * This method will contruct the iframe for IE browsers
		 **/
		createIframe: function (divId, frameId, src)
		{
			var playerDiv = document.getElementById(divId);
			
			var iframe = document.getElementById(frameId);
			
			if (iframe)
			{
				// remove the current iframe
				playerDiv.removeChild(iframe);
				iframe = null;
			}
			
			// create a new iframe
			iframe = document.createElement("iframe");
			iframe.setAttribute("id", frameId);
			iframe.setAttribute("frameBorder","0");
			iframe.style.border = "0px";
			iframe.setAttribute("marginheight","0");
			iframe.setAttribute("marginwidth","0");
			iframe.setAttribute("height","450");
			iframe.setAttribute("width","800");
			iframe.setAttribute("scrolling","no");
			iframe.setAttribute("src",src);
			iframe.style.visibility = "visible";
			
			playerDiv.appendChild(iframe);
		},
		
		/**
		 * This method attaches the sharethis button to the element identified by elid
		 *
		 * @param elid	the DOM element id of the element to which to attach the 
		 * @param subj  object containing fields about the movie trailer
		 */
		attachShare: function(elid, subj)
		{
			var param1 = {title:"HD Movie Trailers", url:"http://www.fandango.com/hdmovietrailers"};
			var param2 = {button:false, onmouseover:false};
			
			var el = document.getElementById(elid);
			if (el)
			{
				var obj = {};
				
				if (!subj)
				{
					obj = SHARETHIS.addEntry(param1, param2);
				}
				else
				{				
					//replace param1
					param1 = getShareThisParameter(subj);
					obj = SHARETHIS.addEntry(param1, param2);
				}
				obj.attachButton(el);
			}
		},
		
		/**
		 * This method attaches the modified (for Twitter) sharethis button to the element identified by elid
		 *
		 * @param elid	the DOM element id of the element to which to attach the 
		 * @param subj  object containing fields about the movie trailer
		 */
		attachTwitterDialog : function(elid, subj)
		{
			var param1 = {title:"HD Movie Trailers", url:"http://www.fandango.com/hdmovietrailers"};
			var param2 = {button:false, onmouseover:false};

			var el = document.getElementById(elid);			
			if (el)
			{
				var obj = {};
				if (!subj)
				{
					obj = SHARETHIS.addEntry({title:"HD Movie Trailers", url:"http://www.fandango.com/hdmovietrailers"}, param2);
				}
				else
				{	
					// replace param1			
					param1 = getShareThisParameter(subj);		
					obj = SHARETHIS.addEntry(param1, param2);
				}
				obj.attachChicklet('twitter', el);
			}
		},
		
		/**
		 * provides access to the movie id
		 */
		getMovieId: function(){
			return this._movieId;
		},
		
		/**
		 * allows setting of the movie id
		 *
		 * @param val string containing movie id
		 */
		setMovieId: function(val){
			this._movieId = val;
		},
		
		/**
		 * provides acces to movie title
		 */
		getMovieTitle: function()
		{
			return this._movieTitle;
		},
		
		/**
		 * allows the setting of the movie title
		 *
		 * @param val string containing the movie title
		 */
		setMovieTitle: function(val)
		{
			this._movieTitle = val;
		},
		
		/**
		 * this method truncates the clip name at the colon and
		 * returns the string to the left of the colon (assuming the string
		 * is the movie title).
		 */
		truncateClipName: function(str)
		{
			if (str.indexOf(':') != -1)
			{
				var fields = str.split(':');
				return fields[0];
			}
			return str;
		},
		
		/**
		 * This method returns the object that caches the tweets' movie id and title
		 * for last successfully retrieved list of tweets.
		 */
		getTweetsCache: function(){
			return this._tweetsCache;
		},
		
		/**
		 * This method sets the cache object that holds the movie id and title for
		 * the last successfully retrieved list of tweets.
		 */
		setTweetsCache: function(mid, mvtitle){
			this._tweetsCache = {};
			this._tweetsCache.movieId = mid;
			this._tweetsCache.movieTitle = mvtitle;
		}
			
	}; // end of object returned by this function
	
})();
