var curTab;
var returnURL;
var plScrolling = false;
MN.TP.PLAYER_WIDTH = 482;
MN.TP.PLAYER_HEIGHT = 362;
MN.TP.fp = null; //flash player reference

function CustomPlayerLoaded(player){
	//init the tabs
	var tabLinks = $('tab_nav').getElementsByTagName('a');
	for(var i = 0; i < tabLinks.length; i++){
		MN.Event.Observe(tabLinks[i], 'click', TabClicked);
	}
	curTab = $(MN.TP.curChnl.name);
	if(curTab)
		curTab.parentNode.className += ' active';

	try{
		if(window.opener){
			returnURL = window.opener.location.href;
			MN.Event.Observe($('back_home'), 'click', ReturnToHome);
		}
	}
	catch(e){
	}
	if($('mn_send_to_friend'))
		MN.TP.InitS2F();

	// Set up pointer to flash ad player & set its affiliate
	MN.TP.fp = $('mn_flashPlayer');
	if(typeof GEO == 'object')
		MN.TP.fp.SetAffiliate(GEO.affiliate);

	// Initialize volume to saved value if available, or default to 75%
	var savedVolume = MN.Cookie.Get('move_player_volume');
	if(savedVolume != null) {
		player.Volume(savedVolume);
	}
	else {
		player.Volume(75);
	}

	//Set up other observes
	MN.Event.Observe(player, 'TimelineLoaded', MN.ad.onTimelineLoaded);
	MN.Event.Observe(player, 'NextClip', MN.ad.onNextClip);
	MN.Event.Observe(player, 'VolumeChanged', OnVolumeChanged);

	MN.Event.Observe($('mn_pl_scroll_up'), 'mousedown', function(){plScrolling = true;MN.TP.qmp.playlist.ScrollUp();});
	MN.Event.Observe($('mn_pl_scroll_up'), 'mouseup', function(){plScrolling = false;} );
	MN.Event.Observe($('mn_pl_scroll_up'), 'mouseout', function(){plScrolling = false;} );

	MN.Event.Observe($('mn_pl_scroll_down'), 'mousedown', function(){plScrolling = true;MN.TP.qmp.playlist.ScrollDown();});
	MN.Event.Observe($('mn_pl_scroll_down'), 'mouseup', function(){plScrolling = false;} );
	MN.Event.Observe($('mn_pl_scroll_down'), 'mouseout', function(){plScrolling = false;} );
}

function OnVolumeChanged(newVol){
	MN.Cookie.Set('move_player_volume', newVol); //create session cookie
}

function TabClicked(evt){
	evt = evt || window.event;
	var src = evt.srcElement || evt.target;
	if(src != curTab){
		if(curTab)
			curTab.parentNode.className = curTab.parentNode.className.replace('active', '');
		src.parentNode.className += ' active';
		MN.TP.SwitchToChannel(src.id);
		curTab = src;
	}
}

// var affiliate = MN.GetPageParams().affiliate || 'test1';
var affiliateAds = getAffiliateAdZones(GEO.affiliate);
MN.ad = {
	'qvt': undefined, // Store ref to QVT
	'moveAd': null, // store ref to most recent ad from MoveAds (in case flash can't find one)
	'returnClipNumber': -1,
	'context': -1,
	'position': -1,
	'scrubPos': -1,
	'adPosition': 'preroll',
	'adServer': 'wbadsrv.movenetworks.tv',
	'affiliate': GEO.affiliate,
	'affiliateAds': affiliateAds,
	'adSplitInited': false,
	'useNational': false,
	'flashAd': false,

	'onTimelineLoaded' : function(qvt)
	{
		MN.QVT._qvtCache = {};
		if(qvt.Title(0) && qvt.Title(0) == '_ad')
		{
			MN.ad.displayAdBreaks(qvt);
			MN.Event.Observe(MN.TP.qmp, 'PlayStateChanged', MN.ad.onPlayStateChanged);
		}
		else
		{
			if(!qvt.inited)
			{
				MN.ad.qvt = qvt;
				var clips = qvt.Metadata('clips');
				var adPosition = 1;

				for(var i=0; i < clips.length; i++)
				{
					var clip = clips[i];
					if (i == 0)
						clip.segmentAvailable = true;
					if(clip['ad_semantics'] && !clip.position)
					{
						clip.position = '5'; // midroll
						clip.adPosition = 'midroll' + adPosition++;
					}
				}
				qvt.inited = true;
				qvt.playedPost = false;
			}
			MN.Event.StopObserving(MN.TP.qmp, 'PlayStateChanged', MN.ad.checkPlayStateScrubbed);
			MN.Event.Observe(MN.TP.qmp, 'PlayStateChanged', MN.ad.checkPlayStateScrubbed);
			MN.ad.displayAdBreaks(qvt);
		}
	},

	'displayAdBreaks' : function(qvt)
	{
		var adbreaks = $('mn_timeline_adbreaks');
		while(adbreaks.childNodes.length > 0)
			adbreaks.removeChild(adbreaks.childNodes[0]);
		var clips = qvt.Metadata('clips');
		for(var i=0; i < clips.length-1; i++)
		{
			var clip = clips[i];
			if(clip['ad_semantics'])
			{
				var div = document.createElement('div');
				var pos = qvt.ClipToTimeline(i, 0);
				var left = parseInt( (pos/MN.TP.qmp.Duration()) * $('mn_timeline').offsetWidth, 10);
				div.style.left = (i > 1) ? left - (2 * i) + 'px' : left + 5 + 'px';
				div.className = (clip.adPlayed == true) ? 'adPlayed' : '';
				$('mn_timeline_adbreaks').appendChild(div);
			}
		}
	},

	'onPlayStateChanged' : function(oldS, newS)
	{
		// Return if end of ad
		if(newS == MN.QMP.PS.MediaEnded)
		{
			var qvt = MN.TP.qmp.CurrentQVT();
			if(qvt.Title(0) && qvt.Title(0) == '_ad')
			{
				MN.Event.StopObserving(MN.TP.qmp, 'PlayStateChanged', MN.ad.onPlayStateChanged);
				MN.ad.returnToEpisode();
			}
		}
	},

	'returnToEpisode' : function()
	{
		var pos = MN.ad.qvt.ClipToTimeline(MN.ad.returnClipNumber, 0);
		// MN.TP.qmp.Play(MN.ad.qvt, pos);
		MN.ad.scrubPos = (MN.ad.scrubPos == -1) ? parseFloat(pos) : MN.ad.scrubPos; // set scrubPos to either where the user clicked or the beginning of the next clip, so we can set position when playback begins

		// We're going to call Play(url,0) so rewind/ff works through whole program, not limited to the startPos of the correct clip or selected timeline position
		// So, set up a temporary observe so when playback starts again, we can quickly set the correct position
		MN.Event.Observe(MN.TP.qmp, 'PlayStateChanged', MN.ad.returnPlayStateChanged);
		var startClip = MN.ad.qvt.TimelineToClip(MN.ad.scrubPos).clipNum;
		if(startClip != 0)
			MN.TP.qmp.Play(MN.ad.qvt,MN.ad.qvt.Metadata('clips')[startClip].rangeStart);
		else
			MN.TP.qmp.Play(MN.ad.qvt,0);
		MN.ad.toggleControls('show');
		setTimeout(function() { MN.TP.qmp.Paused(false); }, 1000);
	},

	'returnPlayStateChanged' : function(oldS,newS){
		if(newS == MN.QMP.PS.Playing){
			MN.ad.stopFlashAd(); //hide flash player and playlist ad after content is going, else you may see an annoying remnant
			if(MN.TP.qmp.scrubbing) MN.TP.Play(); // if ad was hit while scrubbing, reset SDK & page scrubbing variables
			if(MN.ad.scrubPos > 0)
				MN.TP.qmp.CurrentPosition(MN.ad.scrubPos);
			MN.ad.scrubPos = -1;
			MN.Event.StopObserving(MN.TP.qmp, 'PlayStateChanged', MN.ad.returnPlayStateChanged);
		}
	},

	'onNextClip' : function(clipNum) 
	{
		var qvt = MN.ad.qvt;
		var clips = qvt.Metadata('clips');
		if(clipNum == -1)
		{
			MN.ad.returnClipNumber = 0;
			MN.ad.makeVideoCall('4','preroll'); // 4 for preroll
			return;
		}
		var clip = clips[clipNum];
		if(clip['ad_semantics'])
		{
			log('MN.ad.onNextClip', 'in an ad', 'position = ', clip.position);
			if(clips[clipNum]) {
				if(clips[clipNum].adPlayed) //don't play the same adbreak twice
					return;
				else { //mark the ad so it only plays once, and mark the next segment available
					clips[clipNum].adPlayed = true;
					if(clips[clipNum+1]){
						clips[clipNum+1].segmentAvailable = true;
						MN.ad.scrubPos = (MN.ad.scrubPos == -1) ? parseFloat(clips[clipNum+1].range.split(',')[0]) : MN.ad.scrubPos; //set scrubPos
					}
				}
			}

			MN.TP.qmp.Paused(true);
			MN.ad.adPosition = clip.adPosition;
			// MN.ad.returnClipNumber = clipNum + 1;
			MN.ad.returnClipNumber = clipNum;
			MN.ad.makeVideoCall(clip.position, clip.adPosition); // 5 for midroll
		}
		else
		{
			MN.ad.processClip();
		}
	}, 

	'randomHex' : function(length)
	{
		var str = '0123456789abcdef'; // all hex values
		var ret = '';
		for(var i=0; i < length; i++)
		{
			var ch = str.charAt(Math.round(Math.random() * (str.length-1)));
			ret += ch;
		}
		return ret;
	},

	'URLEncode' : function(clearString) {
		var output = '';
		var x = 0;
		clearString = clearString.toString();
		var regex = /(^[a-zA-Z0-9_.]*)/;
		while (x < clearString.length) {
			var match = regex.exec(clearString.substr(x));
			if (match != null && match.length > 1 && match[1] != '') {
				output += match[1];
				x += match[1].length;
			} else {
				if (clearString[x] == ' ')
					output += '+';
				else {
					var charCode = clearString.charCodeAt(x);
					var hexVal = charCode.toString(16);
					output += '%' + ( hexVal.length < 2 ? '0' : '' ) + hexVal.toUpperCase();
				}
				x++;
			}
		}
		return output;
	},

	'getPosition' : function()
	{
		var position = parseInt(MN.ad.position, 10);
		if(position == 4)
		{
			return ['preroll','preroll'];
		}
		else if(position == 5)
		{
			return ['midroll',MN.ad.adPosition];
		}
		else if(position == 6)
		{
			return ['postroll','postroll'];
		}
		return ['preroll','preroll'];
	},

	'makeVideoCall' : function(pos,adPos)
	{
		MN.ad.position = pos;
		window.frames['ad_video'].location = 'video_ad.html?pos=%s&pos2=%s&cb=%s'.format(pos, adPos, MN.ad.randomHex(8));
	},

	'handleVideoAd' : function(ad)
	{
		MN.ad.moveAd = ad;
		if(MN.ad.context == -1)
			MN.ad.context = ad.context;
		//return to content after setting campaign unless channel has video ads or this is the preroll of caterogyID 5 (ad-test channel)
		if(MN.TP.curChnl.videoAds && !(MN.TP.curChnl.categoryID == 5 && MN.ad.adPosition == 'preroll')){
			MN.ad.toggleControls('hide'); //hide player controls, we'll restore when the video ad is done
			if(MN.ad.useNational){ //national looks for flash ads first
				//play a flash ad
				MN.ad.flashAd = true;
				MN.ad.handleFlashAd();
			}
			else{
				//play a move ad
				MN.ad.handleMoveAd();
			}

			MN.ad.joinClips(); //join clips while ad plays (avoid playback delays, be ready to populate timeline with adbreaks)
		}
		else{
			MN.ad.returnToEpisode();
		}
		if(!MN.ad.useNational){
			//affiliate banner ads are served through MoveAds
			MN.ad.handleBannerAd({type:'move',zone:'bottom',width:728,height:90});
			MN.ad.handleBannerAd({type:'move',zone:'middle',width:300,height:60});
			MN.ad.handleBannerAd({type:'move',zone:'right',width:160,height:600});
		}
		else{
			//national banner ads are served through DoubleClick / Ads.com
			MN.ad.handleBannerAd({type:'doubleclick',zone:'bottom',tile:1,width:728,height:90});
			//middle ad being handled by Flash? Either use from Lightningcast or makes the call below (if uncommented, Flash not set up to make the DC call)
			MN.ad.handleBannerAd({type:'doubleclick',zone:'middle',tile:2,width:300,height:60});
			MN.ad.handleBannerAd({type:'doubleclick',zone:'right',tile:3,width:160,height:600});
		}
	},

	'handleMoveAd' : function()
	{
		MN.ad.flashAd = false;
		var url = MN.ad.moveAd.video_url;
		url = (url.indexOf('qmx') == -1 && url.indexOf('qvt') == -1) ? 'http://qmplive07.xlontech.net/wbvod/ads/1F/output.qmx' : url; //if the video url returned isn't a qmx or qvt, use a default qmx
		MN.ad.stopFlashAd(); //make sure any flash ads are stopped and hidden
		MN.Event.Observe(MN.TP.qmp, 'TimelineLoaded', MN.ad.moveAdLoaded);
		MN.TP.qmp.PlayClip(url, '_ad', 0);
	},

	'handleBannerAd' : function(ad)
	{
		//don't try to do this for an invalid ad zone
		if (typeof ad != 'object' || ad.zone != 'right' && ad.zone != 'middle' && ad.zone != 'bottom' && ad.zone != 'playlist')
			return;
		var adZone = ad.zone;
		var adSpace = 'movead_' + adZone;
		var iframe_src = '';

		switch(ad.type){
			case 'move':
				var zone = MN.ad.useNational ? MN.ad.affiliateAds[adZone][1] : MN.ad.affiliateAds[adZone][0];
				iframe_src = 'http://%s/moveads/www/delivery/afr.php?zoneid=%s&source=%s&context=%s&cb=%s'.format(MN.ad.adServer,zone,MN.ad.getPosition()[1],MN.ad.context,MN.ad.randomHex(8));
				break;
			case 'lightningcast':
				iframe_src = 'lc_ad.html?width=%s&height=%s&src=%s&href=%s'.format(ad.width,ad.height,MN.ad.URLEncode(ad.href),MN.ad.URLEncode(ad.clickThru));
				break;
			case 'doubleclick':
				iframe_src = 'dc_ad.html?width=%s&height=%s&tile=%s'.format(ad.width,ad.height,ad.tile);
				break;
		}

		// Check to see to the div already has an iframe.
		var frames = $(adSpace).getElementsByTagName('iframe');
		if (frames && frames[0] != null) { // If so, set the source.
			frames[0].src = iframe_src;
		}
		else { // If not, create the iframe for this ad zone
			$(adSpace).innerHTML = '<iframe id="%s_zone" name="%s_zone" framespacing="0" frameborder="no" scrolling="no" style="width:%spx; height:%spx;">'.format(adZone,adZone,ad.width,ad.height);
			$(adSpace).getElementsByTagName('iframe')[0].src = iframe_src;
		}
		log('--- ' + adZone + ' ad: ' + iframe_src);
	},

	'joinClips' : function(){
		// this function is to remove unnecessary ad clips, thus enabling rew/ff across as much of the show as possible
		var clips = MN.ad.qvt.Metadata('clips');
		for(var i = clips.length - 1; i > 0; i--){
			if(clips[i].ad_semantics){ //this is an ad, see if we can join the surrounding clips
				if(clips[i-1].segmentAvailable == true && clips[i+1] && clips[i+1].segmentAvailable == true){ //segment before and after ad are both available; join them!
					clips.splice(i,1); //remove the ad clip
					var newStart = clips[i-1].range.split(',')[0]; //startPos of pre-ad clip
					var newStop = clips[i].range.split(',')[1]; //stopPos of post-ad clip
					clips.splice(i,1); // remove the post-ad clip
					// adjust the properties of the new, combined clip
					clips[i-1].range = newStart + ',' + newStop;
					clips[i-1].duration = eval(newStop - newStart);
					clips[i-1].rangeEnd = newStop;
					clips[i-1].tlStopTime = newStop;
				}
			}
		}
	},

	'toggleControls' : function(state)
	{
		var toggleArray = ['mn_tools', 'mn_timeline', 'mn_timeline_scrubber', 'mn_duration', 'mn_controls'];
			if(state == 'hide'){
				for(var i = 0; i < toggleArray.length; i++){
					$(toggleArray[i]).style.visibility = 'hidden';
				}
				$('ad_status').style.visibility = 'visible';
				MN.SetInnerText($('ad_status'),'Your video will resume after this brief message.');
			}
			else if(state == 'show'){
				for(var i = 0; i < toggleArray.length; i++){
					$(toggleArray[i]).style.visibility = 'visible';
				}
				$('ad_status').style.visibility = 'hidden';
				MN.SetInnerText($('ad_status'),'');
			}
	},

	'moveAdLoaded' : function()
	{
		MN.Event.StopObserving(MN.TP.qmp, 'TimelineLoaded', MN.ad.moveAdLoaded);
		MN.ad.displayCountdown();
	},

	'displayCountdown' : function()
	{
		var player = MN.ad.flashAd ? MN.TP.fp : MN.TP.qmp;
		var sec = Math.ceil(player.Duration() - player.CurrentPosition()) || '0';
		var secTail = (sec != 1) ? ' seconds.' : ' second.';
		if($('ad_status').style.visibility == 'visible'){
			var tailText = (sec <= 0) ? 'after this brief message.' : 'in ' + sec + secTail;
			MN.SetInnerText($('ad_status'),'Your video will resume ' + tailText);
			setTimeout('MN.ad.displayCountdown()',500);
		}
		else{
			MN.SetInnerText($('ad_status'),'');
			sec = -1;
			secText = '';
		}
	},

	'checkPlayStateScrubbed' : function(oldS, newS)
	{
		//make sure ads up to current point have played (did they scrub?)
		if(newS == MN.QMP.PS.Playing){
			MN.ad.processClip();
		}
	},

	'processClip' : function()
	{
		if(MN.TP.curChnl.videoAds){
			var clips = MN.ad.qvt.Metadata('clips');
			var clip = MN.TP.qmp.CurrentClip();
			// make sure the directly previous ad has played
			for(var i = clip; i > 0; i--){
				if(clips[i].ad_semantics){
					if(!clips[i].adPlayed || clips[i].adPlayed != true){
						MN.ad.scrubPos = parseFloat(MN.TP.qmp.CurrentPosition()); //remember where the user scrubbed to
						MN.ad.onNextClip(i);
					}
					break;
				}
			}
		}
	},

	'toggleFlashPlayer' : function(state)
	{
		$('mn_player').style.visibility = (state == 'hide') ? 'visible' : 'hidden';
		$('mn_flashPlayer').style.width = (state == 'hide') ? '0px' : MN.TP.PLAYER_WIDTH + 'px';
	},

	'togglePlaylistAd' : function(state)
	{
		$('mn_playlist').style.left = (state == 'hide') ? '' : '-9000px';
		$('movead_playlist').style.display = (state == 'hide') ? 'none' : 'block';
	},

	'handleFlashAd' : function()
	{
		MN.TP.fp.PlayAd();
		//Flash will toggle the playlist ad if it has something to put there
		var myQVT = {'clips':[{'range':'0,1800'}],'shows':[{'start':0.0,'title':'_ad'}]};
		MN.TP.qmp.Play(myQVT);
		MN.ad.displayCountdown();
		MN.ad.toggleFlashPlayer('show');
	},

	'stopFlashAd' : function()
	{
		MN.TP.fp.StopAd();
		MN.ad.toggleFlashPlayer('hide');
		MN.ad.togglePlaylistAd('hide');
	},

	'noFlashAd' : function()
	{
		MN.ad.handleMoveAd();
	},

	'reset' : function()
	{
		MN.ad.stopFlashAd(); //make sure flash ads are stopped and hidden if the user changes shows
		MN.ad.scrubPos = -1;
		MN.ad.adPosition == 'preroll';
	}
};


MN.PB = {
	'host':'http://cms025.sv1.qcn3.movenetworks.com',
	'publisher':'wbvod',
	'currentClipIndex':null,
	'clipList':[],
	'viewElements':[],
	'playListContainer':$('mn_playlist'),
	'categoryIdToIndex': {},
	'attemptS2F':true
};
MN.PB.init = function()
{
	var categoryList = CatalogListing.categoryList;
	for(var i=0; i < categoryList.length; i++)
	{
		var category = categoryList[i];
		MN.PB.categoryIdToIndex[category.id] = i;
	}
	log('publish data loaded');
};
MN.PB.init();

MN.PB.getCategoryClips = function(categoryID) {
	MN.PB.viewElements = [];
	var category = CatalogListing.categoryList[MN.PB.categoryIdToIndex[categoryID]];
	if(!category) { logError('MN.PB.getCategoryClips', 'category is empty'); return; }
	while(MN.PB.playListContainer.childNodes.length > 0)
			MN.PB.playListContainer.removeChild(MN.PB.playListContainer.childNodes[0]);
	var clips = category.clipList;
	MN.PB.clipList = clips;
	for(var i=0; i < clips.length; i++)
	{
		var div = document.createElement('div');
		div.className = 'mn_clip';
		div.clip = clips[i];

		var thumbDiv = document.createElement('div');
		thumbDiv.className = 'mn_show_thumbnail';
		if(clips[i].thumbnail)
		{
			var thumbImg = document.createElement('img');
			thumbImg.src = MN.URL.Join(MN.PB.host, clips[i].thumbnail.thumb_url);
			thumbDiv.appendChild(thumbImg);
		}
		else
		{
			var thumbDivPlace = document.createElement('div');
			thumbDivPlace.className = 'imgPlaceHolder';
			thumbDiv.appendChild(thumbDivPlace);
		}
		div.appendChild(thumbDiv);

		var titleDiv = document.createElement('div');
		titleDiv.className = 'mn_show_title';
		var clipTitle = clips[i].name || clips[i].title;
		if(typeof clipTitle == 'undefined' || clipTitle.length == 0)
			clipTitle = 'No Title';
		clipTitle = clipTitle.replace('[WIDEVINE] ','').replace('[widevine] ','').replace('[Widevine] ','');
		MN.SetInnerText(titleDiv, clipTitle);
		div.appendChild(titleDiv);

		var descDiv = document.createElement('div');
		descDiv.className = 'mn_show_desc';
		if(clips[i].description && clips[i].description.length > 0)
			MN.SetInnerText(descDiv, clips[i].description);
		div.appendChild(descDiv);

		MN.Event.Observe(div, 'click', MN.MakeBound(div, function(evt)
		{
			MN.PB.getClipTimeline(this.clip);
			MN.PB.highlightClip(this.clip);
		}));

		div.style.visibility = 'visible';
		div.style.display = 'block';

		MN.PB.playListContainer.appendChild(div);
		MN.PB.viewElements[MN.PB.viewElements.length] = div;
	}
	if(clips.length > 0)
	{
		var playClip = 0;
		//check for s2f link on pageload, and try use it if there is one -- else play first clip in playlist
		if(MN.TP.params.show && MN.TP.params.ep && MN.PB.attemptS2F){
			MN.PB.attemptS2F = false;
			for (i = 0; i < clips.length; i++){
				if(clips[i].id == MN.TP.params.ep){
					playClip = i;
				}
			}
		}
		MN.PB.getClipTimeline(clips[playClip]);
		MN.PB.highlightClip(clips[playClip]);
		MN.PB.currentClipIndex = playClip;
		if(clips.length > 5) { //show playlist scroller if more than 5 clips
			$('mn_pl_scroller').style.visibility = 'visible';
			$('mn_pl_scroll_up').style.visibility = 'visible';
			$('mn_pl_scroll_down').style.visibility = 'visible';
		}
		else{
			$('mn_pl_scroller').style.visibility = 'hidden';
			$('mn_pl_scroll_up').style.visibility = 'hidden';
			$('mn_pl_scroll_down').style.visibility = 'hidden';
		}
	}
	else
		MN.TP.qmp.Stop();
};
MN.PB.forward = function(){
	if(MN.PB.currentClipIndex + 1 < MN.PB.clipList.length)//play next clip
	{
		MN.PB.currentClipIndex += 1;
		MN.PB.getClipTimeline(MN.PB.clipList[MN.PB.currentClipIndex]);
		MN.PB.highlightClip(MN.PB.clipList[MN.PB.currentClipIndex]);
	}
};
MN.PB.backward = function(){
	if(MN.PB.currentClipIndex - 1 >= 0)//play next clip
	{
		MN.PB.currentClipIndex -= 1;
		MN.PB.getClipTimeline(MN.PB.clipList[MN.PB.currentClipIndex]);
		MN.PB.highlightClip(MN.PB.clipList[MN.PB.currentClipIndex]);
	}
};
MN.PB.highlightClip = function(clip){
	for(var i=0;i<MN.PB.viewElements.length;++i)
	{
		if(MN.PB.viewElements[i].clip.id === clip.id)//show this one
		{
			MN.CSS.AddClass(MN.PB.viewElements[i],'mn_highlight');
			MN.PB.currentClipIndex = i;
		}
		else
		{
			MN.CSS.RemoveClass(MN.PB.viewElements[i],'mn_highlight');
		}
	}
	var clipBox = MN.PB.viewElements[MN.PB.currentClipIndex];
	var clipTopVisible = !(clipBox.offsetTop < (MN.PB.playListContainer.offsetTop * -1));
	var clipOffsetBottom = clipBox.offsetTop + clipBox.offsetHeight + 5; //5 margin on the bottom, too
	var clipBottomVisible = !(clipOffsetBottom > ($('mn_playlist_container').offsetHeight + (MN.PB.playListContainer.offsetTop * -1) + 4));
	var newScrollVal = (MN.PB.currentClipIndex > 0) ? Math.ceil((clipOffsetBottom - 4) / MN.PB.playListContainer.offsetHeight * 100) : 0;
	if(!clipTopVisible || !clipBottomVisible){
		MN.TP.qmp.playlist._scroller.Value(newScrollVal);
		MN.TP.qmp.playlist._ScrollChanged(newScrollVal);
	}
};
MN.PB.getClipTimeline = function(clip) {
	MN.TP.qmp.Stop();
	MN.ad.reset();
	var qvt = '%s/cms/publish/vod/vodclip/%s/%s.qvt'.format(MN.PB.host, MN.PB.publisher, clip.id);
	MN.ad.context = -1;
	var CB = function(url, response, headers)
	{
		var qvt = MN.EvalJSON(response);
		// create a postroll if CONFIG specifies video ads for current channel
		if(MN.TP.curChnl.videoAds)
			qvt.clips.push({'ad_semantics':'ad_dynamic', 'range':'0,1', 'position':'6', 'adPosition':'postroll'});
		MN.PB.getClipTimelineCB(qvt);
	};
	MN.QVT.LoadQVT(qvt, CB);
//	MN.TP.qmp.Play(qvt, -1);
//	Call('GetClipTimeline', MN.PB.getClipTimelineCB, -1, 'clip_id', clip.id);
};
MN.PB.getClipTimelineCB = function(qvt) {
	var q = MN.QVT.AcquireQVT(qvt);
	if(q.IsLoading())
		MN.Event.Observe(q, 'TimelineLoaded', MN.PB.onQVTLoaded);
	else
		MN.PB.onQVTLoaded(q);
};
MN.PB.onQVTLoaded = function(qvt) {
	MN.Event.StopObserving(qvt, 'TimelineLoaded', MN.PB.onQVTLoaded);
	MN.ad.qvt = qvt;
	MN.ad.onNextClip(-1);
};

/*****************************************************************
 *          QMPInstall replacement messages / functions          *
 *****************************************************************/
MN.QMPInstall.MSG_DOWNLOADMODULES = '<div id="moveplay_install" style="background-color:black;position:absolute;top:130px;left:195px;z-index:1000;"><span class="moveplay_featuretitle" id="modulemessagespan"><img src="images/twohalfmen/loading.gif" width="66" height="66" border="0" alt="" /></span>';
//due to a bug in SDK 7.8 multiple DOWNLOADMODULES messages may display. Fix!
MN.QMPInstall._ShowModulesMessage = function() {
    var playerParent = $(QI.playerParentID);
    var mm = $('modulemessage');
    if (!mm) {
        var e = document.createElement('div');
        e.id = 'modulemessage';
        e.innerHTML = QI.MSG_DOWNLOADMODULES;
        playerParent.appendChild(e);
    }
    else {
        var mms = $('modulemessagespan');
        mms.innerHTML = QI.MSG_DOWNLOADMODULES;
    }
};
//IE might not hide the player correctly to show MSG_DOWNLOADMODULES. WARN THE USER!
if(MN.QMPInstall.os == 'win' && MN.QMPInstall.browser != 'mozilla'){
	MN.QMPInstall.MSG_BASE_INSTALLING_POSTFIX = '<span class="moveplay_featuredesc">  Once successfully loaded, a video will start playing in this window.<br><br>'
		+ 'If this is your first time installing the Move Media Player, this area may turn black after installation for up to 5 minutes while first-time configuration finishes, depending on your Internet connection. This is normal.</span>'
	    + '<br><br>'
	    + '<div id="moveplay_progressouter"><div id="moveplay_progressinner"></div></div><span id="moveplay_installprogressmsg">Loading...</span>'
	    + '</div>';
}
// MN.QMPInstall._HideClient = function() {
//     if (!QI.playerHidden)
//     {
//         playerObj = $(QI.playerID);
// 		if(MN.nonIE) {
// 	        QI.playerWidth = playerObj.style.width;
// 	        QI.playerHeight = playerObj.style.height;
// 	        playerObj.style.width="1px";
// 	        playerObj.style.height="1px";
// 		}
// 		else {
// 			playerObj.style.zIndex = 0;
// 			playerObj.style.display = 'none';
// 		}
//         QI.playerHidden = true;
//         log("Client hidden");
//     }
// };
// MN.QMPInstall._UnhideClient = function() {
//     if (QI.playerHidden)
//     {
//         playerObj = $(QI.playerID);
// 		if(MN.nonIE) {
// 	        playerObj.style.width = QI.playerWidth;
// 	        playerObj.style.height = QI.playerHeight;
// 		}
// 		else {
// 			playerObj.style.display = '';
// 		}
//         QI.playerHidden = false;
//         log("Client Un-hidden");
//     }
// };