//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);
};

//Array remove
Array.prototype.remove=function(){
    var args=arguments;
    var idxs=new Array();
    var ret=new Array();
    for(var i=0;i<args.length;i++) {
        if(typeof(args[i]) == "number" && args[i] < this.length){
            idxs.push(args[i]);
        }
    }
    idxs.sort(function(a,b) { return b-a; });
    for(var i=0; i<idxs.length; i++) {
        var el = this.splice(idxs[i],1).pop();
        ret.unshift(el);
    }
    return ret;
};

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._qvt;
    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 = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
    this._monthArray = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
    
    if(dropdownID && $(dropdownID)){
        this._dropdown = new MN.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){
	log('PLAYLIST: timeline loaded');
    //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())
        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 playlist is currently displaying
		this._Populate(qvt);
		if(qvt.PrimaryURL() == this._curURL) //if reloading the qvt being watched, try keep current show in view at all times
			this._ScrollIntoView(this._curShow);
	}
};

_pp._OnShowChanged = function(showNum, title){
    var qvt = this.qmp.CurrentQVT();
    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;
};

_pp._Populate = function(qvt){
    this._curURL = qvt.PrimaryURL();
	if(this._qvt)
		this._qvt.DecRef();
	this._qvt = qvt;  //Save the qvt that is loaded, used for ABC News
	this._qvt.IncRef();

	if(!qvt.inited){
		//ABC: check for weekend loop shows
		if(qvt.shows.length > 1 && qvt.shows[0].title == '' && qvt.shows[0].desc == '' && qvt.shows[1].title == 'WEEKEND LOOP'){
			qvt.shows.remove(0);
			log('PLAYLIST: found weekend loop, trimmed num of shows to: ', qvt.shows.length);
		}
		for(var i = 0; i < qvt.shows.length; i++){
			if(qvt.shows[i].title == 'WEEKEND LOOP'){
				qvt.shows[i].title = qvt.shows[i].desc;
				qvt.shows[i].title = 'ABC\'s 24-Hour Live Stream has the Latest Headlines, Health, Entertainment and Business News';
				qvt.shows[i].weekendLoop = true;
			}
		}
		qvt.inited = true;
	}

    log('populating: ', qvt.PrimaryURL());
    //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';
	if(qvt.PrimaryURL().search('byid') != -1){
		contentType = 'vod';
	}	
    var curShow;
    var highlight;
	log('PLAYLIST POPULATING - NO. OF SHOWS: ', qvt.shows.length);
	//var num = Math.min(qvt.shows.length, 42); REMOVED FOR NOW
	var num = qvt.shows.length;
	log('PLAYLIST: cutting num of shows to: ', num);

    for(var i = 0; i < num; i++){  //ABC only wants 7 pages of clips at the most, which comes out to 42
        curShow = qvt.shows[i];

        curShow.thumbnail = curShow.thumbnail || GENERIC_SHOW_IMAGE;
        highlight = (this._SameURLAsPlayer() && i == this._curShow);
        
        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 = date.month + "/" + date.day + "/" + date.year; //month is 1 based
    }
    else if(contentType == 'vod')
        text = qvt.Metadata('title') || 'No Title';
        
    this.FireEvent('Populated', this._curURL, text);
};

_pp._CreateShowBox = function(show, posToDatetime, highlight){
    var newBox = MN.PopulateTemplate(this._boxTemplate, show, posToDatetime, show.weekendLoop);
    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', '');});

	newBox.title = show.desc;  //ABC specific?
	if(show.weekendLoop) //ABC likes to put in a weekend loop message / title that is too long, and overflow:hidden no worky right for IE... try to make it fit
		newBox.style.fontSize = '9px';

    return newBox;
};


_pp._ShowClicked = function(start){
    if(!this._SameURLAsPlayer()){
        log('Playlist: changing qvt');
        this.qmp.Play(this._qvt, 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];
	if(elem.offsetHeight > 0){
    	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);
    }
};

_pp.CurrentPage = function(num){
	if(num == null)
		return this._curPage;
	else{	
		//function takes a number starting with 1
		if(num > 0 && num <= this._pagePositions.length){
			this._canvas.style.top = -this._pagePositions[num - 1] + 'px';
			if(this._scroller){
				this._scroller.Value(this._pagePositions[num - 1]);
			}
			this._curPage = num - 1;
			this.FireEvent('PageChanged', num, 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 - 1;
        for(var i = 0; i < length; i++){
            this._dropdown.remove(this._dropdown.options[0]);
        }

        newOption = document.createElement('option');
        newOption.innerHTML = '<i>Loading...&nbsp;</i>';
        newOption.setAttribute('value', 'loading');
        newOption.disabled = true;
        this._dropdown.add(newOption, null);
    }
};

_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('url') == 'loading'){
				log('found loading');
                loadOpt = this._dropdown.remove(loadOpt);
                numOfOptions--;
            }
        }

		log('removed Loading....');
        
        //update content dropdown
		if(numOfOptions == 0)
			numOfOptions = 1;
        var diff = urlList.length - (numOfOptions - 1);
        var url;
        for(var i = 0; i < diff; i++){
            url = urlList[numOfOptions - 1 + i];
            this._dropdown.add(this._CreateContentOption(url), null);
        }
        
        //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.add(loadOpt, null);  
		    else{
		        var newOption = document.createElement('option');
				newOption.setAttribute('value', 'loading');
                newOption.innerHTML = '<i>Loading...&nbsp;</i>';
                newOption.disabled = true;
                this._dropdown.add(newOption, null);
		    }
		}
    }
};

_pp._CreateContentOption = function(url){
	log('creating option with url: ', 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 = 'live';//qvt.Metadata('mn_content_type') || 'vod';
    if(contentType == 'live'){
        var date = qvt.StartDatetime();
	    text = text = date.month + "/" + date.day + "/" + date.year;
    }
    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('url');
	log(url);
    if(url != 'loading'){
        qvt = MN.QVT.AcquireQVT(url);
		if(window.CustomDropdownSelected)
			CustomDropdownSelected();
	    this._Populate(qvt);	
	    MN.QVT.ReleaseQVT(qvt);
    }
};

delete _pp;