var MOVE_PLAYER_WIDTH = 440;
var MOVE_PLAYER_HEIGHT = 337;
var MOVE_PLAYER_CHROME_HEIGHT = 83;
var movePlayer; // Move Player object
var pbvod; // Move Publish VOD Interface object
var pbbf; // Move Publish Broadcast Feed Interface object
var pbwf; // Move Publish Web Feed Interface object
var CATEGORYOBJ; 
var firstLoad = true; //Variable to track if this is the first page load
var firstFeedLoad = true;
var numClips = 4; 
var curPage = 1;
var numPages;
var HOST = 'cms020.sv1.qcn3.movenetworks.com'; 
var PUBLISHER = 'ksl'; 
var CHANNEL = 1;
var CATEGORY = 8;
var WEBFEED = 1;
var FEED_LOOKAHEAD_HOURS = 50;
var FEED_DISPLAY_REFRESH = 60; // seconds between UI refreshes
var showBoxTemplate;// = MN.Widget.FindNonTextChild($('mn_playlist'));
/**** STARTUP ****/
MN.Event.Observe(window, 'load', function() {
	MN.AutoPlayer.RegisterSkin({
		name : 'standard',
		maximized : false,
		version : 0,
		markup : '\
		<div id="ap_class_wrapper" class="mn_standard mn_background">\
			<div class="mn_preloadedImages"></div> \
			<div id="ap_scrubstatus" class="mn_scrubstatus"></div> \
		  <div id="ap_show_title_wrapper" class="mn_show_title_wrapper"> \
			</div> \
      <div id="ap_playerwrap" class="mn_playerwrap"></div> \
      <div id="ap_controls" class="mn_controls ap_controls"> \
      <div class="mn_ctrls_left"></div> \
      <div class="mn_ctrls_center"></div> \
      <div class="mn_ctrls_right"></div> \
				<ul id="ap_buttons" class="mn_buttons"> \
					<!--<li><a id="ap_back" title="Jump Back" href="#" class="mn_back mn_hidden" onclick="return false"></a></li>--> \
					<li><a id="ap_rewind" title="Rewind" href="#" class="mn_rewind" onclick="return false"></a></li> \
					<li><a id="ap_pause" title="Pause" href="#" class="mn_pause" onclick="return false"></a></li> \
					<li><a id="ap_unpause" title="Play" href="#" class="mn_play" onclick="return false"></a></li> \
					<li><a id="ap_fastforward" title="Fast Forward" href="#" class="mn_fast_forward" onclick="return false"></a></li> \
					<!--<li><a id="ap_jumpforward" title="Jump Forward" href="#" class="mn_jump_forward mn_hidden" onclick="return false"></a></li>--> \
					<li><a id="ap_golive" title="Go Live" href="#" class="mn_go_live" onclick="return false" style="visibility:hidden;display:none"></a></li> \
				</ul> \
				<div id="ap_bitrateplaystate" class="mn_player_status"></div> \
				<div id="ap_tl_container" class="mn_tl_container"> \
					<div id="ap_duration" class="mn_duration"><span id="ap_posdur"></span></div> \
					<div id="ap_tradtimelinetrack" class="mn_timeline"> \
					<div class="mn_timeline_scrubber" title="Drag to adjust playback position"></div> \
				</div> \
			</div> \
			<ul class="mn_tools"> \
				<li> \
					<div id="ap_volumetrack" orientation="horizontal" class="mn_volume_bar"> \
						<div class="mn_volume_thumb" title="Drag to adjust audio"></div> \
					</div> \
				</li> \
        <li><a id="ap_send_to_friend" href="#" class="mn_send_to_friend mn_hidden" title="Send to a Friend">Send to a Friend</a></li> \
				<li><a id="ap_faq" class="mn_help mn_popup" href="[[URL]]support/faq.html" title="Frequently Asked Questions">FAQ</a></li> \
				<li><a id="ap_popout" href="#" class="mn_pop_out mn_hidden" title="Pop Out" onclick="return false">Popout Window</a></li> \
				<li><a id="ap_popin" href="#" class="mn_pop_in mn_hidden" title="Pop In" onclick="return false">Popout Window</a></li> \
				<li><a id="ap_maximize" href="#" class="mn_maximize" title="Fullscreen" onclick="return false">Full Screen</a></li> \
				<li><a id="ap_minimize" href="#" class="mn_minimize mn_hidden" title="Collapse" onclick="return false">Collapse</a></li> \
			</ul> \
		</div>',
		extraHeight : 83, // extra pixels for graphics above and below the player itself
   	extraWidth : 3,
		methods : 
		{
			_OnLoad : function()
			{
				MN.Event.Observe(window, "resize", this.OnWindowResize);
				this.GetElement('scrubstatus').style.visibility = 'visible';
				this.GetElement('show_title_wrapper').style.visibility = 'visible';
				this.GetElement('controls').style.visibility = 'visible';
        //MN.Event.Observe(this.GetElement('send_to_friend'), "click", OpenSendBox);
        var func = MN.MakeBound(this.GetElement('faq'), MN.PopupWin);
        MN.Event.Observe(this.GetElement('faq'), 'click', func);
        this.GetElement('faq').onclick = function(){return false};
      },
			maximize_click : function(evt)
			{
				this.maximized = true;
       	MN.CSS.AddClass(document.body, "maximized");
				MN.CSS.RemoveClass(this.GetElement('minimize'), 'mn_hidden');
				MN.CSS.AddClass(this.GetElement('maximize'), 'mn_hidden');
        $('mn_playlist_container').style.display = 'none';
		    document.body.style.marginLeft = '0';
        window.moveTo(0,0);
        window.resizeTo(screen.availWidth, screen.availHeight);
        this.OnWindowResize();
        return true;
			},
			minimize_click : function(evt)
			{
				this.maximized = false;
				MN.CSS.RemoveClass(document.body, "maximized");
				MN.CSS.RemoveClass(this.GetElement('maximize'), 'mn_hidden');
				MN.CSS.AddClass(this.GetElement('minimize'), 'mn_hidden');
        $('mn_playlist_container').style.display = 'block';
        $('move_player').style.width = MOVE_PLAYER_WIDTH + 3 + 'px';
				movePlayer.Width(MOVE_PLAYER_WIDTH);
				movePlayer.Height(MOVE_PLAYER_HEIGHT);
        this.OnWindowResize();
			},
			OnWindowResize : function()
			{
				if(this.maximized)
				{
					var size = MN.GetWindowSize();
					$('move_player').style.width = size[0] + 'px';
					movePlayer.Width(size[0]);
					movePlayer.Height(size[1] - MOVE_PLAYER_CHROME_HEIGHT);
				}
        var newTlWidth = this.GetElement('tl_container').offsetWidth - this.GetElement('duration').offsetWidth - 15;
        if (newTlWidth > 0)
          this.GetElement('tradtimelinetrack').style.width = newTlWidth + 'px';
			}
		}
	});
});

MN.Event.Observe(window, "load", OnWindowLoaded);
function OnWindowLoaded() {
	// Add a "debug" param to the URL to show a debugging pane
	var params = MN.GetPageParams();
	if(params.debug)
		MN.Log.ShowPane(500);
		
	// Create player using the standard skin
	MN.AutoPlayer.CreatePlayer("standard", "move_player", OnPlayerLoaded, MOVE_PLAYER_WIDTH, MOVE_PLAYER_HEIGHT + MOVE_PLAYER_CHROME_HEIGHT);
	
	// Default status
	SetStatus($('pb_categories_data'), nodataHTML);
	MN.Event.Observe($('pb_input_category'), "change", HandlePBCategoryInput);
	
	// Default clip properties
	UpdateClipProperty("QVT", "none");
	UpdateClipProperty("QMX", "none");
	UpdateClipProperty("Bitrate", "none");
}

function OnPlayerLoaded(player) {
	movePlayer = player;
	$('mn_playlist_container').style.display = 'block';
  	// Register player event handlers
  	HandlePBCXInput();
}


/**** PUBLISH HANDLING ****/
function OnWebFeedLoaded(feedObj) {
	if(!feedObj)
	{
		SetStatus($('pb_live'), errorHTML.format("Error Loading Web Feed"));
	}
	else
	{
		SetStatus($('pb_live'), "");
		RefreshWebFeedDisplay();
		window.setInterval(RefreshWebFeedDisplay, FEED_DISPLAY_REFRESH*1000)
	}
	pbvod.LoadChannel(CHANNEL, OnChannelLoaded);
}

function RefreshWebFeedDisplay() {
	RefreshLiveDisplay();
}

function RefreshLiveDisplay() {
	var feedId = WEBFEED;
	var start = new Date();
	var end = new Date((new Date(start)).setHours(start.getHours()+FEED_LOOKAHEAD_HOURS)); // Add hours (curse JS date functions)
	var currentShow = pbwf.GetWebFeedShowsPlayingInRange(feedId, start, start, 1, /.+/);
	var container = $('mn_playlist_live_container');
	var containerState = (container.state) ? container.state : 0;
	var showState = (currentShow.length) ? currentShow[0].startUtcTimestamp : 0;

	if(container.state == null || containerState != showState) {
		log("updating live display", containerState, showState);
		if(currentShow.length) {
			currentShow = currentShow[0];
			container.style.display = "block";
			container.state = currentShow.startUtcTimestamp;
			MN.SetInnerText($('pb_live_show_title'), currentShow.title);
			$('pb_live_playlink').onclick = function() {
				PlayLiveWebFeed(feedId);
			}
			if(firstFeedLoad) {
				PlayLiveWebFeed(feedId);
			}
		} else {
			container.style.display = "none";
			container.state = 0;
		}
		RefreshUpcomingDisplay();
	}
	firstFeedLoad = false;
}

function RefreshUpcomingDisplay() {
	var feedId = WEBFEED;
	var start = new Date();
	var end = new Date((new Date(start)).setHours(start.getHours()+FEED_LOOKAHEAD_HOURS)); // Add hours (curse JS date functions)
  var upcomingShows = pbwf.GetWebFeedShowsStartingInRange(feedId, start, end, 2, /.+/);
	
	MN.SetInnerText($('pb_live_upcoming'), "");
	for (var i=0; i < upcomingShows.length; i++) {
		var e = CreateEventBox(upcomingShows[i]);
		$('pb_live_upcoming').appendChild(e);
	};
}


function OnChannelLoaded(channelObj) {
	if(!channelObj)
	{
		SetStatus($('mn_playlist'), errorHTML.format("Error Loading Channel"));
		OnCategoryLoaded(null);
	}
	else if(!channelObj.categoryList || !channelObj.categoryList.length)
	{
		SetStatus($('mn_playlist'), noRecordsHTML.format("No Categories In Channel"));
		OnCategoryLoaded({});
	}
	else
	{
		SetStatus($('mn_playlist'), "");
		OnCategoryLoaded(pbvod.GetCategory(CHANNEL, CATEGORY));
	}
}

function OnCategoryLoaded(categoryObj,pageNum) {
  CATEGORYOBJ = categoryObj;
  if (pageNum == null){
    pageNum = curPage;
  }
  curPage = pageNum;
  var i = 0;
  var smallNum = 0;
  var largeNum = numClips;
  this._viewer = $('mn_playlist');
  this._foo =  $('mn_clip_container');
  if(!showBoxTemplate){
    showBoxTemplate = MN.Widget.FindNonTextChild($('mn_playlist'));
    this._boxTemplate = $('mn_playlist').removeChild(showBoxTemplate);
    this._boxTemplate.style.display = 'block';
    this._boxTemplate.style.visibility = 'visible';
  }
  
    var highlight = 0;
    this._numOfPages = Math.ceil(categoryObj.clipList.length / numClips);
    numPages = this._numOfPages;
    CreatePagination(this._numOfPages,curPage);

    if (this._foo){
      if ( this._foo.hasChildNodes() ){
        while ( this._foo.childNodes.length >= 1 ){
          this._foo.removeChild( this._foo.firstChild );       
        } 
      }
     // this._canvas = document.createElement('div');
     // this._canvas.setAttribute('id', 'mn_clip_container');
    //  this._viewer.appendChild(this._canvas);
    } else {
      this._canvas = document.createElement('div');
      this._canvas.setAttribute('id', 'mn_clip_container');
      this._viewer.appendChild(this._canvas);
    }
    
    largeNum = largeNum * curPage;
    smallNum = largeNum - numClips;
    for(i=smallNum; i < categoryObj.clipList.length && i !=largeNum; i++) {
      curShow = categoryObj.clipList[i];
      if(firstLoad && movePlayer.CurrentPlayState() == 0){
        highlight = 1;
        firstLoad = false;
      }
      this._canvas.appendChild(CreateShowBox(curShow, null, highlight,categoryObj.id));
      highlight = 0;
		}
}

function CreateShowBox(show, posToDatetime, highlight,categoryId){
    var newBox = MN.PopulateTemplate(this._boxTemplate, show, posToDatetime);
    newBox.style.cursor = 'pointer';
    newBox.id = "episode_" + categoryId + "_" + show.id;
    if(highlight){
      newBox.className += ' mn_highlight';
      PlayEpisode(categoryId, show.id)
    }
    MN.Event.Observe(newBox, 'click', function(){PlayEpisode(categoryId, show.id)});
    //IE doesn't support :hover for anything but anchors, so add mouseovers
    MN.Event.Observe(newBox, 'mouseover', function(){newBox.className += ' mn_highlight';});
    MN.Event.Observe(newBox, 'mouseout', function(){newBox.className = newBox.className.replace('mn_highlight', '');});
    return newBox;
}

function CreateEventBox(show){
  var e = document.createElement("div");
	var t = document.createElement("div");
	var s = document.createElement("div");
	var dt;
	e.className = "upcoming_event_entry";
	t.className = "event_title";
	s.className = "event_start";
	
	MN.SetInnerText(t,show.title);
  
  dt = new Date(show.startUtcTimestamp); 
  var output = MN.PI.utils.DateFormat(dt, "D M jS H:i") + " (local time)"; 
  MN.SetInnerText(s,output);
	
	e.appendChild(t);
	e.appendChild(s);
	
	return e;
}
	
function CreatePagination(numOfPages,cPage) {
  var container = $('mn_playlist_page_nav'); 
  //Clear out pagination
  container.innerHTML = ' ';
  if (numPages != 1 && numPages != 0){
    var prevImg = document.createElement('img');
    var nextImg = document.createElement('img');
  
    prevImg.src = 'images/arrow_left.png';
    container.appendChild(prevImg);
    prevImg.style.cursor = 'pointer';
    prevImg.className = 'playlist_page_nav';
    MN.Event.Observe(prevImg, 'click', function(){prevPg();});
       
    if (numOfPages > 1){
      for(var i=1; i <= numOfPages; i++) {
        if(curPage == i){
          var newLink = document.createElement("span");
          MN.SetInnerText(newLink, i);
          container.appendChild(newLink);
          newLink.style.fontWeight = 'bold';
          newLink.className = 'playlist_page_nav';
          newLink.id = "page_" + i;
        } else {
          var newLink = document.createElement("a");
          newLink.href = '#';
    	    newLink.onclick = function(pageNum){return function(){openPage(pageNum)}}(i);
          MN.SetInnerText(newLink, i);
          container.appendChild(newLink);
          newLink.className = 'playlist_page_nav';
          newLink.id = "page_" + i;
        }
      } 
    }
    
    nextImg.src = 'images/arrow_right.png';
    container.appendChild(nextImg);
    nextImg.style.cursor = 'pointer';
    nextImg.className = 'playlist_page_nav';
    MN.Event.Observe(nextImg, 'click', function(){nextPg();});
  }
}

function openPage(pageNum){
  if(pageNum != curPage){
    OnCategoryLoaded(CATEGORYOBJ,pageNum);
  }
}

function nextPg(){
  if(curPage < numPages){
    openPage(curPage + 1);
  } else if (curPage == numPages) {
    openPage(1);
  }
}

function prevPg(){
  var goTo = curPage - 1; 
  if(goTo!=0){
    openPage(goTo);
  } else {
    openPage(numPages);
  }
}

function PlayEpisode(categoryId, clipId) {
	var clip = pbvod.GetClip(CHANNEL, categoryId, clipId);
	// Show the share button
	//$('player_QMP_share').style.display = 'block';
	if(clip) {
		episode = categoryId + "-" + clipId;
    movePlayer.Play(clip.qvt);
    // Set a selected class on the nav element
    SelectNavEpisodeElement($(episode));
	}
}

function PlayLiveWebFeed(feedId) {
	var qvt = pbwf.GetWebFeedQVT(feedId);
	movePlayer.Play(qvt, -1);
}

function SelectNavEpisodeElement(element) {
	// Clear currently selected element
	var episodeList = $('mn_clip_container').childNodes;
	for(var i=0; i < episodeList.length; i++) {
		MN.CSS.RemoveClass(episodeList[i], "mn_highlight");
	}
	// Set the selected element
  //alert(element.id);
	MN.CSS.AddClass(element, "mn_highlight");
}

function SendToFriend(){
  $('mn_send_friend').style.visibility ="visible"; 
  $('mn_playlist_container').style.visibility= 'hidden'; 
}
/**** FORM HANDLING ****/
var loadingHTML = "<span class=\"loadingMsg\">%s</span>";
var errorHTML = "<span class=\"errorMsg\">%s</span>";
var nodataHTML = "<span class=\"nodataMsg\">Loading...</span>";
var noRecordsHTML = "<span class=\"noRecordsMsg\">%s</span>";
function HandlePBCXInput() {
	var start = new Date();
	var end = new Date((new Date(start)).setHours(start.getHours()+FEED_LOOKAHEAD_HOURS)); // Add hours (curse JS date functions)
	SetStatus($('pb_live'), loadingHTML.format("Loading Live..."));
	SetStatus($('mn_playlist'), loadingHTML.format("Loading On Demand..."));
	pbvod = new MN.PI.VODPublishInterface(HOST, PUBLISHER);
	pbbf = new MN.PI.BroadcastFeedPublishInterface(HOST, PUBLISHER);
	pbwf = new MN.PI.WebFeedPublishInterface(HOST, PUBLISHER);
	pbwf.LoadWebFeed(WEBFEED, start, end, OnWebFeedLoaded); // Web feed triggers on demand load
}

function HandlePBCategoryInput() {
	var cte = $('pb_input_category').options;
	var categoryId = cte[cte.selectedIndex].value;
	var category = pbvod.GetCategory(CHANNEL, categoryId);
	OnCategoryLoaded(category);
}


// Recursively traverses a category list, building an Option for each one.
// Subcategory names are prepended with a buffer string
function CategoryListOptionsFactory(categoryList,depth) {
	var optionArray = [];
	depth = (depth == null) ? 0 : depth;
	if(categoryList) {
		for(var i=0; i < categoryList.length; i++) {
			var bufferStr = "";
			for(var j=0; j < depth; j++) {
				bufferStr += "---";
			}
			optionArray.push(new Option(bufferStr + categoryList[i].name, categoryList[i].id));
			optionArray = optionArray.concat(CategoryListOptionsFactory(categoryList[i].categoryList,depth+1));
		}
	}
	return optionArray;
}

// Replaces an element with a status message.  To remove the status and show
// the element again, pass an empty string for statusHTML.
function SetStatus(e, statusHTML) {
  if(statusHTML) {
		if(e.previousSibling != null && e.previousSibling.className == "statusMsg") {
			var le = e.previousSibling;
		} else {
			var le = document.createElement("div");
			e.parentNode.insertBefore(le, e);
			le.className = "statusMsg";
		}
		le.innerHTML = statusHTML;
		e.style.display = "none";
	} else if(e.previousSibling.className == "statusMsg") {
		e.parentNode.removeChild(e.previousSibling);
		e.style.display = "block";
	}
}
//MN.PopulateTemplate-----------------------------------------------------------------------//
//This function is used for both the playlist and the show timeline.  It takes a DOM element//
//(template) and populates it with data from the showObj (which in these two cases          //
//originates from a qvt) by finding special class names in the element and its children.    //
//------------------------------------------------------------------------------------------//
MN.PopulateTemplate = function(template, showObj, posToDatetime){
    var newBox = template.cloneNode(true);
    var curElement;
    for(var curProp in showObj){
        if(curProp == 'tlStartTime' || curProp == 'tlStopTime')
            curProp = curProp.replace('tlS', 's');
    
        //append "mn_show" to the property and search for and element with that class
        elements = MN.GetElementsByClassName(newBox, 'mn_show_' + curProp, true);
        if(curProp == 'startTime' || curProp == 'stopTime' || curProp == 'duration'){ //these three use timestamps
            var timeFormat;
            var ts;
            if(curProp == 'startTime' || curProp == 'stopTime')
                curProp = 'tlS' + curProp.slice(1);  //the property in the showObj is tlStartTime or tlStopTime
                
            for(var i = 0; i < elements.length; i++){
                curElement = elements[i];
                timeFormat = curElement.innerHTML || 'HH:MM:SS';
                
                //force to 24 hour timestamp when necessary.  The absence of posToDatetime
                //means that the content is "vod", and so we force a 24 hour timestamp
                if(curProp == 'duration' || !posToDatetime)
                    timeFormat = timeFormat.toUpperCase();
                
                if(posToDatetime)
                    ts = MN.ConvertToTimestamp(posToDatetime(showObj[curProp]), timeFormat);
                else
                    ts = MN.ConvertToTimestamp(showObj[curProp], timeFormat);
                 
                curElement.innerHTML = ts;
            }
        }
        else if(curProp == 'thumbnail'){
            for(var i = 0; i < elements.length; i++){
                elements[i].innerHTML += '<img src="' + showObj[curProp]['thumb_url'] + '" />';
            }
        }
        else{
            for(var i = 0; i < elements.length; i++){
                elements[i].innerHTML = showObj[curProp];
            }
        }
    }
    
    return newBox;
}

//MN.GetElementsByClassName-----------------------------------------------------------------//
//This function searches an element's children for a specific class name, and returns an    //
//array of those elements.  The third option, recursive, is a boolean flag that tells the   //
//function to search the children's children, and the children's childrens' children, etc.  //
//------------------------------------------------------------------------------------------//
MN.GetElementsByClassName = function(element, className, recursive){
	if(!element)
		return;
	
    var array = [];
    if(element.hasChildNodes()){
        var child;
        for(var i = 0; i < element.childNodes.length; i++){
            child = element.childNodes[i];
            if(child.nodeType == 1){ //make sure it is not a text node
                //I don't think the order matters much
                if(child.className == className)
                    array.push(child);
                if(recursive)
                    array = array.concat(this.GetElementsByClassName(child, className, recursive));
            }
        }
    }
    return array;
}

//MN.TP.PopupWin----------------------------------------------------------------------------//
//This is called when a user clicks on an anchor that has been set as a "popup" via			//
//MN.TP.InitPopups.  It opens a new window to the link.										//
//------------------------------------------------------------------------------------------//
MN.PopupWin = function(){
    //the function has been bound via MN.MakeBound, so "this" references the anchor element
    var width = this.getAttribute('popup_width') || 650;
    var height = this.getAttribute('popup_height') || 664;
    window.open(this.getAttribute('href'),'popup','width=' + width + ',height=' + height + ',status=yes,scrollbars=yes,resizable=yes,location=no,toolbar=no');
}

