// @author Tim Major
// @customized Ben Loveridge
// @revision 20071217-0955
//   -added support for publish webfeeds without changing player behavior

//Fix for vslider bug
MN.Widget.VSlider.prototype.Value = function(y, fireEvent)
{   // gets/sets the value of the slider and moves the thumb accordingly
    if (y == null)
        return this.curValue;

    y = this.minValue + this.ClipValue(y);
    var oldValue = this.curValue;
    this.curValue = y;
    this.thumb.style.top = this.CalcThumbPosition(y) + 'px';

    if (fireEvent)
        this.FireEvent('ValueChanged', this.curValue);
};

MN.Playlist = MN.Class(MN.EventSource);
_pp = MN.Playlist.prototype;

_pp.initialize = function(qmp, divID, dropdownID, scrollID){
    MN.EventSource.prototype.initialize.apply(this);
    this.qmp = qmp;
    this._epg;
    this._curURL = '';
    this._curShow = 0;
    this._viewer = $(divID);
    if(scrollID && $(scrollID)){
        this._scroller = new MN.Widget.VSlider($(scrollID), 0, 100);
        MN.Event.Observe(this._scroller, 'ValueChanged', this._ScrollChanged);
    }
    //these are used for pagination
    this._curPage = 0;
    this._numOfPages = 0;
    //arrays for dropdown
    this._dayArray = ["Domingo", "Segunda", "Ter&ccedil;a", "Quarta", "Quinta", "Sexta", "S&aacute;bado"];
    this._monthArray = ["Janeiro", "Fevereiro", "Mar&ccedil;o", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"];
    
    if(dropdownID && $(dropdownID)){
        this._dropdown = $(dropdownID);
        MN.Event.Observe(this._dropdown, 'change', this._SelectContent);
    }
        
    //grab the show box template
    var showBoxTemplate = MN.Widget.FindNonTextChild($(divID));
    if(showBoxTemplate){
        this._boxTemplate = $(divID).removeChild(showBoxTemplate);
        this._boxTemplate.style.display = 'block';
        this._boxTemplate.style.visibility = 'visible';
    }
    else{
        this._boxTemplate = document.createElement('table');
        var newRow = this._boxTemplate.insertRow(-1);
        var newCell = newRow.insertCell(-1);
        newCell.className = 'mn_show_thumb';
        newCell = newRow.insertCell(-1);
        newCell.className = 'mn_show_startTime';
        newCell = newRow.insertCell(-1);
        newCell.className = 'mn_show_title';
    }
    
    //create the scroll pane widget
    this._canvas = document.createElement('div');
    this._viewer.appendChild(this._canvas);
    this._scrollPane = new MN.Widget.ScrollPane(divID);
    //this._viewer.style.overflow = 'visible';
    //W3C browsers add a bit of "padding" to the offsetTop number
    //when there is a border around the playlist.  The offsetTop
    //number needs to be set to 0 initially, and the offset "offset" needs
    //to be used everytime thereafter
    this._offset = -this._canvas.offsetTop;
    
    MN.Event.Observe(this.qmp, 'TimelineLoaded', this._OnTimelineLoaded);
    MN.Event.Observe(this.qmp, 'ShowChanged', this._OnShowChanged);
}

_pp._OnTimelineLoaded = function(qvt){
    //the player has either loaded a new url, or the open-ended timeline
    //has reloaded and we need to refresh the playlist
    // if((qvt.PrimaryURL() != this._curURL) || qvt.IsOpenEnded())
	if((qvt.GetSource() != this._curURL) || qvt.IsOpenEnded())
        this._LoadQVT(qvt, qvt.IsOpenEnded());
    else
        log('playlist: timeline already loaded in playlist');
}

_pp._LoadQVT = function(qvt, reload){
    MN.Event.StopObserving(qvt, 'TimelineLoaded', this._LoadQVT);
    if(!reload){
		this._curShow = 0;
		this._Populate(qvt);
	}
	// else if(this._curURL == '' || qvt.PrimaryURL() == this._curURL){ //only repopulate on reload if reloaded playlist is currently displaying
	else if(this._curURL == '' || qvt.GetSource() == this._curURL){ //only repopulate on reload if reloaded playlist is currently displaying
		this._Populate(qvt);
		// if(qvt.PrimaryURL() == this._curURL) //if (re)loading the qvt being watched, try to scroll the current show into view
		if(qvt.GetSource() == this._curURL) //if (re)loading the qvt being watched, try to scroll the current show into view
			this._ScrollIntoView(this._curShow);
	}
}

_pp._OnShowChanged = function(showNum, title){
    var qvt = this.qmp.CurrentQVT();
	// if(this._curURL != qvt.PrimaryURL()) //if the show changes, make sure we show the right playlist data (shows & dropdown)
	if(this._curURL != qvt.GetSource()) //if the show changes, make sure we show the right playlist data (shows & dropdown)
		this._LoadQVT(qvt);
	if(this._dropdown && this._dropdown.options[0].value != 'loading')
		this._dropdown.options[0].selected = true; //default to showing the first date, then change it if necessary (today.qvt will never be found, but will always be top item)
	for(var i = 0; i < this._dropdown.options.length; i++){ //show the right day in dropdown
		if(this._dropdown.options[i].value == qvt.GetSource()){
			this._dropdown.options[i].selected = true;
			break;
		}
	}
	
    if(showNum < 0 || showNum >= qvt.ShowCount())
        showNum = qvt.ShowCount() - 1;
        
    //do the highlights
    if(this._SameURLAsPlayer()){
        var showBoxes = this._canvas.childNodes;
        if(showBoxes[this._curShow])
            showBoxes[this._curShow].className = showBoxes[this._curShow].className.replace('mn_highlight', '');
        showBoxes[showNum].className += ' mn_highlight';
        this._ScrollIntoView(showNum); 
    }    
    
    this._curShow = showNum;
}

_pp._SameURLAsPlayer = function(){
    // return this.qmp.CurrentQVT().PrimaryURL() == this._curURL;
	return this.qmp.CurrentQVT().GetSource() == this._curURL;
}

_pp._Populate = function(qvt){
    // this._curURL = qvt.PrimaryURL();
	this._curURL = qvt.GetSource();

    log('populating');
    //clear out the old playlist
    while(this._canvas.childNodes.length > 0){
        this._canvas.removeChild(this._canvas.childNodes[0]);
    }
 
    var contentType = qvt.Metadata('mn_content_type')  || MN.TP.curChnl.contentType || 'vod';
    var curShow;
    var highlight;

	// determine how many shows to populate -- live Publish QVT? Non-Publish QVT? VOD?
	var length;
	if(qvt.IsAnchored()) { //timeline is anchored (Publish live QVT), so let's limit the output through the current show
		length = qvt.TimelineToShow(qvt.GetTimelineNow()) + 1; //returns 0-based show number, convert to 1-based show length
		length = (length > qvt.shows.length) ? qvt.shows.length : length; //don't try to create boxes for non-shows (yesterday's QVT TimelineToNow may return an extra, non-existent show, and break page logic)
	}
	else //something like a live non-Publish or VOD QVT
		length = qvt.shows.length;
	
    for(var i = 0; i < length; i++){
        curShow = qvt.shows[i];
        curShow.thumbnail = curShow.thumbnail || 'images/clip_thumb.jpg';
        highlight = (this._SameURLAsPlayer() && i == this._curShow);
        
        //TODO: timezoneOverride
        if(contentType == 'live')
            this._canvas.appendChild(this._CreateShowBox(curShow, qvt.PosToDatetime, highlight));  
        else if(contentType == 'vod')
            this._canvas.appendChild(this._CreateShowBox(curShow, null, highlight));
    }
    
    this._UpdatePages();
    
    //get the text to pass with the event
    if(contentType == 'live'){
        var date = qvt.StartDatetime();
	    text = this._dayArray[date.dow] + ", " + this._monthArray[date.month - 1] + " " + date.day + ", " + date.year; //month is 1 based
    }
    else if(contentType == 'vod')
        text = qvt.Metadata('title') || 'No Title';

	if(this.qmp){
		// if(qvt.PrimaryURL() == MN.TP.qmp.CurrentQVT().PrimaryURL()){ //we just populated the currently-playing QVT, so try to scroll current show into view
		if(qvt.GetSource() == this.qmp.CurrentQVT().GetSource()){ //we just populated the currently-playing QVT, so try to scroll current show into view
			this._ScrollIntoView(this._curShow);
		}
	}
        
    this.FireEvent('Populated', this._curURL, text);
}

_pp._CreateShowBox = function(show, posToDatetime, highlight){
    var newBox = MN.PopulateTemplate(this._boxTemplate, show, posToDatetime);
    newBox.style.cursor = 'pointer';
    if(highlight)
        newBox.className += ' mn_highlight';
    
    var func = MN.MakeBound(this, this._ShowClicked);
    MN.Event.Observe(newBox, 'click', function(){func(show.tlStartTime)});
    //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;
}

_pp._ShowClicked = function(start){
    if(!this._SameURLAsPlayer()){
        log('Playlist: changing qvt');
        this.qmp.Play(this._curURL, start);
    }
    else{
        log('same qvt: playing');
        this.qmp.CurrentPosition(start);
    }
}

_pp._ScrollIntoView = function(showNum){
    //check if the element needs to scroll into view
    var elem = this._canvas.childNodes[showNum];
    var elemBottom = elem.offsetTop + elem.offsetHeight;
    var relBottom = elemBottom + (this._canvas.offsetTop + this._offset); //offsetTop is a negative number
    var relTop = elem.offsetTop + (this._canvas.offsetTop + this._offset);
    
    if(relBottom > this._viewer.offsetHeight){
        this.PageDown();
        this._ScrollIntoView(showNum);
    }
    else if(relTop < 0){
        this.PageUp();
        this._ScrollIntoView(showNum);
    }
}


_pp._UpdatePages = function(){
    var numBoxesAllowed = Math.floor(this._viewer.offsetHeight / this._canvas.firstChild.offsetHeight);
    var pageBump = this._canvas.firstChild.offsetHeight * numBoxesAllowed;
    //clear old playlist
    //this._numOfPages = Math.ceil(this._canvas.offsetHeight / this._viewer.offsetHeight);
    this._numOfPages = Math.ceil(this._canvas.childNodes.length / numBoxesAllowed);
    this._curPage = 0;
    this._canvas.style.top = '0px';
    this._pagePositions = [];
    for(var i = 0; i < this._numOfPages; i++){
        this._pagePositions.push(pageBump * i);
    }
    
    if(this._scroller){
        this._scroller.Value(0);
        this._scroller.SetRange(0, this._canvas.offsetHeight - pageBump);
    }
    
    this.FireEvent('PageChanged', this._curPage + 1, this._numOfPages);
}

_pp.PageDown = function(){     
    if(this._curPage < this._numOfPages - 1){
		//this._canvas.style.top = -this._pagePositions[++this._curPage] + 'px';
        this._scrollPane.Position(0, this._pagePositions[++this._curPage]);
        if(this._scroller){
            this._scroller.Value(this._pagePositions[this._curPage]);
        }
        this.FireEvent('PageChanged', this._curPage + 1, this._numOfPages);
    }
}

_pp.PageUp = function(){
    if(this._curPage >= 1){
		//this._canvas.style.top = -this._pagePositions[--this._curPage] + 'px';
        this._scrollPane.Position(0, this._pagePositions[--this._curPage]);
        if(this._scroller){
            this._scroller.Value(this._pagePositions[this._curPage]);
        }
        this.FireEvent('PageChanged', this._curPage + 1, this._numOfPages);
    }
}

//called when the scroller widget changes positions
_pp._ScrollChanged = function(value){
    this._scrollPane.Position(0,value);
    // //find what page we are on
    //     var numBoxesAllowed = Math.floor(this._viewer.offsetHeight / this._canvas.firstChild.offsetHeight);
    //     var pageBump = this._canvas.firstChild.offsetHeight * numBoxesAllowed;
    //     var mid = value + (this._viewer.offsetHeight / 2);
    //     var bottom = value + this._viewer.offsetHeight;
    //     for(var i = this._pagePositions.length - 1; i >=0 ; i--){
    //         if(i == this._pagePositions.length - 1 && bottom >= this._pagePositions[i]){
    //             if(this._curPage != i){
    //                 this._curPage = i;
    //                 log('page changed: ' +  (this._curPage + 1) +  ' of ' + this._numOfPages);
    //             }
    //             return;
    //         }
    //         if(mid >= this._pagePositions[i] && mid < this._pagePositions[i] + pageBump){
    //             if(this._curPage != i){
    //                 this._curPage = i;
    //                 log('page changed: ' +  (this._curPage + 1) +  ' of ' + this._numOfPages);
    //             }
    //             return;
    //         }
    //     }
}

_pp.LoadContent = function(opt){
    //reset the playlist stuff
    if(this._epg){
        MN.Event.StopObserving(this._epg, 'urlLoaded', this._OnURLLoaded);
        this._epg = null;
    }
    this._ResetDropdown();
    
    if(opt instanceof MN.EPG){
        log('playlist.LoadContent: loading EPG'); 
        if(this._dropdown)
            this._dropdown.style.visibility = 'visible';
            
        this._epg = opt;
        if(this._epg.IsDone())
            this._OnURLLoaded(this._epg.urlList, true, this._epg.name);
        else{
            if(this._epg.urlList.length >= 5){
                this._OnURLLoaded(this._epg.urlList, false, this._epg.name, true);
            }
            MN.Event.Observe(this._epg, 'urlLoaded', this._OnURLLoaded);
        }
    }
    else if(opt instanceof MN.QVT.QVT){
        log('playlist.LoadContent: loading qvt');
        if(this._dropdown)
            this._dropdown.style.visibility = 'hidden';
            
        if(opt.IsLoading())
            MN.Event.Observe(opt, 'TimelineLoaded', this._LoadQVT);
        else
            this._LoadQVT(opt);
    }
}

_pp._ResetDropdown = function(){
    if(this._dropdown){
        var length = this._dropdown.options.length;
        for(var i = 0; i < length; i++){
            this._dropdown.removeChild(this._dropdown.options[0]);
        }
        var newOption = document.createElement('option');
        newOption.innerHTML = '<i>Carregando...&nbsp;</i>';
        newOption.setAttribute('value', 'loading');
        newOption.disabled = true;
        this._dropdown.appendChild(newOption);
    }
}

_pp._OnURLLoaded = function(urlList, isDone, name, override){
    if((this._dropdown) && (urlList.length % 5 == 0 || isDone || override)){
        log('playlist._OnURLLoaded: updating dropdown');
        
        //clear the "Loading..." option
        var numOfOptions = this._dropdown.options.length;
        var loadOpt;
        if(numOfOptions > 0){
            loadOpt = this._dropdown.options[numOfOptions - 1];
            if(loadOpt.getAttribute('value') == 'loading'){
                loadOpt = this._dropdown.removeChild(loadOpt);
                numOfOptions--;
            }
        }
        
        //update content dropdown
        var diff = urlList.length - numOfOptions;
        var url;
        for(var i = 0; i < diff; i++){
            url = urlList[numOfOptions + i];
            this._dropdown.appendChild(this._CreateContentOption(url));
        }
        
        //add another "Loading..." option to let the user know that there is still more to load
		if(!isDone){
		    //due to the _ResetDropdown function, loadOpt is guaranteed to exist, but still be safe
		    if(loadOpt)
		        this._dropdown.appendChild(loadOpt);  
		    else{
		        var newOption = document.createElement('option');
                newOption.innerHTML = '<i>Carregando...&nbsp;</i>';
                newOption.setAttribute('value', 'loading');
                newOption.disabled = true;
                this._dropdown.appendChild(newOption);
		    }
		}
    }
}

_pp._CreateContentOption = function(url){
    //because the qvt was cached when the EPG originally grabbed it, AcquireQVT
    //will immediately fetch the full qvt - no observation for TimelineLoaded is needed
    var qvt = MN.QVT.AcquireQVT(url);
    var text = '';
    var contentType = qvt.Metadata('mn_content_type')  || MN.TP.curChnl.contentType || 'vod';
    if(contentType == 'live'){
        var date = qvt.StartDatetime();
	    text = this._dayArray[date.dow] + ", " + this._monthArray[date.month - 1] + " " + date.day + ", " + date.year; //month is 1 based
    }
    else if(contentType == 'vod')
        text = qvt.Metadata('title') || 'No Title';
    
    var newOption = document.createElement('option');
	newOption.setAttribute('value', url);
	newOption.innerHTML = text;
	//if(qvt == MN.TP.qmp.CurrentQVT())
	    //newOption.className = 'highlight';
	MN.QVT.ReleaseQVT(qvt);
	return newOption;
}

_pp._SelectContent = function(){
    var option = this._dropdown.options[this._dropdown.selectedIndex];
    var url = option.getAttribute('value');
    if(url != 'loading'){
        qvt = MN.QVT.AcquireQVT(url);
	    this._Populate(qvt);	
	    MN.QVT.ReleaseQVT(qvt);
    }
}

delete _pp;