/* variable declaration */
var _rrMgr = null;
var _searchWrapper = null;

var _allAirings = null;
var _allFieldSearchAirings = null;
var _name = null;
var _tmsid = null;
var _intWmid = null;
var _query = null;

var _tableDiv;
var _titleDiv;
var _titleDiv1;
var _titleDiv2;
var _airingsFound;
var _rrImgSrc;
var _rrImgSrcRollover;
var _airingUrl;
var _maxSummaryLength;
var _maxTitleLength;
var _sortBy;
var _sortBy2;
var _sortDir;
var _sortDir2;
var _maxAiringsPerPage;
var _lowerBound;
var _upperBound;

var _futureEpisodeCountDiv = null;
var _futureEpisodeWmids = null;
var _futureEpisodeDates = null;

/* constants for the columns */
var columnWidths;
var columnWidthsMetric = "px"
var tdClassName = "tvUpcomingAirings_td";
var tdClassNameShaded = "tvUpcomingAirings_shadedTd";
var headerTdClassName = "tvUpcomingAirings_headerTd";
var selectedTdClassName = "tvUpcomingAirings_selectedTd";
var headerDateTdClassName = "tvUpcomingAirings_headerDateTd";
var selectedDateTdClassName = "tvUpcomingAirings_selectedDateTd";
var trClassName = "tvUpcomingAirings_tr";
var dateClassName = "tvUpcomingAirings_date";
var timeClassName = "tvUpcomingAirings_time";

/* other constants */
var _noneFoundMessage = "Sorry, no airings of this series were found in the next ten days.";
var _maxAiringsPerPageCookie = "MaxAiringsPerPage";

/* search varable */
var k_discoveryWSpath;

function onLoadPage()
{
    _tableDiv = GE("ua_table");
    _titleDiv = GE("ua_title");
    _titleDiv1 = GE("ua_title1");
    _titleDiv2 = GE("ua_title2");

    // hidden input fields
    _name = GE("ua_name");
    _tmsid = GE("ua_tmsid");
    _intWmid = GE("ua_intwmid");
    
    /* search level two variable */
    _query = GE("ua_query");
    _field = GE("ua_field");
    
    _rrImgSrc = GE("ua_rrimgsrc");
    _rrImgSrcRollover = GE("ua_rrimgsrc2");
    _ascendingImgSrc = GE("ua_ascimgsrc");
    _descendingImgSrc = GE("ua_descimgsrc");
    _airingUrl = GE("ua_airingurl");
    _maxSummaryLength = GE("ua_maxsummarylength");
    _maxTitleLength = GE("ua_maxtitlelength");
    _loadingImgSrc = GE("ua_loadingimgsrc");
    _loadingImgStyle = GE("ua_loadingimgstyle");
    
    _svcIncludeUrl = GE("ua_svcincludeurl");
    
    // pagination
    _paginationDiv = GE("ua_padinationdiv");
    _boundsDiv = GE("ua_boundsdiv");
    _maxPerPageDiv = GE("ua_maxperpagediv");
    _pageChooserDiv = GE("ua_pagechooserdiv");
    
    // marking new episodes as NEW!
    _futureEpisodeCountDiv = GE("ua_numfutureepisodes");
    
    if (_futureEpisodeCountDiv != null && _futureEpisodeCountDiv.value > 0)
    {
        _futureEpisodeWmids = new Array(_futureEpisodeCountDiv.value);
        _futureEpisodeDates = new Array(_futureEpisodeCountDiv.value);
        for (var i = 0; i < _futureEpisodeCountDiv.value; ++i)
        {
            _futureEpisodeWmids[i] = GE("ua_episode" + i).value;
            
            var d = new Date(0);
            d.setMilliseconds(Date.parse(GE("ua_episodeairdate" + i).value));
            _futureEpisodeDates[i] = d;
        }
    }
    
    // initial value
    _airingsFound = 0;
    
    // default column widths
    columnWidths = new Array(5)
    columnWidths[0] = 119;
    columnWidths[1] = 50;
    columnWidths[2] = 428;
    columnWidths[3] = 69;

    // primary and secondary sort by value and sort direction defaults
    // 1 - Ascending
    // -1 - Descending
    _sortBy = "date";
    _sortDir = 1;
    _sortBy2 = "channel";
    _sortDir2 = 1;
    
    // set bounds and max per page for pagination
    _maxAiringsPerPage = getCookie(_maxAiringsPerPageCookie);
    if (_maxAiringsPerPage == null)
    {
        _maxAiringsPerPage = _util_maxAiringsPerPage;
    }
    _lowerBound = _util_lowerBound;
    _upperBound = _lowerBound + (_maxAiringsPerPage - 1);
    
    _messageDiv = _titleDiv1;
    _loadingImageDiv = _titleDiv2;
    
    // tv provider fields
    setUpTVProviderVariables();
    
    if (_query != null && _svcIncludeUrl != null)
    {
        k_discoveryWSpath = _svcIncludeUrl.value + "DiscoveryWS";
    
        try
        {
            _searchWrapper = new Microsoft.Msn.Tv.SearchWrapper();
            _searchWrapper.init(k_discoveryWSpath, handleError);
        }
        catch(e)
        {
            handleError();
            return;
        }    
    }

    _rrMgr = createRRObject();
}

function onUnLoadPage()
{
    if (_rrMgr != null)
    {
        _rrMgr.dispose();
    }
    if (_searchWrapper != null)
    {
        _searchWrapper.dispose();
    }
}

function callAllAiringsFunction()
{
    var wmid = (_intWmid != null) ? _intWmid.value : null;
    var name = (_name != null) ? _name.value.toLowerCase() : null;
    var tmsid = (_tmsid != null) ? _tmsid.value : null;
        
    getAllAirings(name, wmid, tmsid);
    
    if (_query == null)
    {
        setTimeout("timeout();", _util_timeOutTime);
    }
}

function handleError()
{
    _tableDiv.innerHTML = "";

    // show that there are now airings found
    _titleDiv1.style.display = "block";
    _titleDiv1.innerHTML = _timeOutMessage;
    _titleDiv2.style.display = "none";
    
    updateHeadendDisplayForError();
}

function handleNoData()
{
    _tableDiv.innerHTML = "";

    // show that there are now airings found
    _titleDiv1.style.display = "block";
    _titleDiv1.innerHTML = _noneFoundMessage;
    _titleDiv2.style.display = "none";
}

function getAllAirings(name, intWmid, tmsId)
{
    // function called upon completion of the get all airings call below
    var onComplete = function(result)
    {
        _listingsFound = true;
        
        _allAirings = result;
        if (!_timedOut) 
        {
            renderResults();
        }
        
        updateHeadendDisplay();
    }
    
    // function called upon completion of the search level 2 call below
    var onCompleteFieldSearch = function(result)
    {
        _listingsFound = true;

        _allFieldSearchAirings = result;
        renderResults();

        updateHeadendDisplay();
    }    
    
    if (_query != null)
    {
        // bogus entry to get provider info
        _timedOut = true;
        getNextAiringIndices("", null, "SH004571230000");
 
        // call to search wrapper level 2
        _searchWrapper.levelTwoSearch(_name.value, _query.value, _field.value, onCompleteFieldSearch);
    }
    else
    {
        // call to the get all airings function
        if (tmsId != null)
        {
            _rrMgr.getAllAiringsWithEncode(name, intWmid, onComplete, tmsId);
        }
        else
        {
            _rrMgr.getAllAiringsWithEncode(name, intWmid, onComplete);
        }
    }
}

function SortAirings(result)
{
    var airings = new Array();
    for(var i=0; i<result.shows.length; i++)
    {
        var show = result.shows[i];
        var schedule = show.Schedule;
        for(var j=0; j<schedule.length; j++)
        {
            airings.push({"show":show, "schedule":schedule[j], "episodeIndex":i, "airingIndex":j});
        }
    }

    // set the appropriate compare values
    var sortFunc = function(a,b)
                    {
                        return compareAirings(b.show, a.show, b.schedule, a.schedule)
                    }

    airings.sort(sortFunc);
    return airings;
}

function recordAiring(episodeIndex, airingIndex, recordSeries)
{
    _rrMgr.doRecord(_allAirings, episodeIndex, airingIndex, recordSeries);
}

function recordLevel2Airing(episodeIndex, airingIndex, recordSeries)
{
    _rrMgr.doRecord(_allFieldSearchAirings, episodeIndex, airingIndex, recordSeries);
}

function renderResults()
{    
    var airingsIndices, episode, airing;
    /* Episode and Airing object members: 
     *   episode:("Title", "LeadActors", "ProgramID", "Actors", "Description",
     *            "Directors", "EpisodeTitle", "Hosts", "LeadHost", "MPAA",
     *            "OtherCredits", "StarRating", "Year");
     *
     *   airing:("ChanID", "Affiliate", "CallLetters", "Duration",
     *           "StartTime", "Repeat", "TVRating", "Channel");
     */

    if (_query == null)
    {
        if (_allAirings.shows.length == 0)
        {
            handleNoData();
            return;
        }

        // get the next episodes
        airingsIndices = getNextAiringsIndices();
    }
    else
    {
        _allAirings = SortAirings(_allFieldSearchAirings);

        _airingsFound = _allAirings.length;
    }
    
    if (_airingsFound == 0)
    {
        handleNoData();
        return;
    }
    
    _upperBound = _lowerBound + (_maxAiringsPerPage - 1);
    if (_upperBound > _airingsFound)
    {
        _upperBound = _airingsFound;
    }
    
    if (_maxAiringsPerPage >= _airingsFound)
    {
        _lowerBound = 1;
        _upperBound = _airingsFound;
    }

    // show the number of results in the title
    _tableDiv.innerHTML = "";
    _tableDiv.style.display = "block";
    if (_query == null)
    {
        _titleDiv.style.display = "none";
        _titleDiv1.style.display = "none";
        _titleDiv2.style.display = "none";
    }
    else
    {
        _titleDiv.style.display = "block";
        _titleDiv1.style.display = "block";
        
        var airingOrAirings = (_airingsFound == 1) ? "airing" : "airings";
        
        _titleDiv1.innerHTML = _airingsFound + " " + airingOrAirings + " of <a href=\"/tv/airing.aspx?title=" + _name.value + 
                                                                                    "&type=series" + 
                                                                                    "&progId=" + _allAirings[0].show.ProgramID + "\" >" + 
                               _name.value + "</a> matching \"" + _query.value + "\" on " + getFriendlyFieldName(_field.value) + ":";
        _titleDiv2.style.display = "none";
    }
    
    var table, tr, td;
    var background = -1;
    var theDate = new Date();
    theDate.setTime(0);
    
    // create the table
    table = document.createElement("table");
    table.className = "tvUpcomingAirings_table";
    table.cellSpacing = 0;

    // render the table
    renderHeader(table);

    // populate the table
    var midnightIndex = 0;
    for (var i = _lowerBound-1; i < _upperBound && i < _util_maxAiringsShown && i < _airingsFound; ++i) 
    {
        if (_query == null)
        {    
            // if empty, move on to the next one
            if (airingsIndices[i][0] == -1) continue;
            
            episode = _allAirings.shows[airingsIndices[i][0]]
            airing = episode.Schedule[airingsIndices[i][1]];
        }
        else
        {
            episode = _allAirings[i].show;
            airing = _allAirings[i].schedule;
        }
        
        // create the row
        tr = table.insertRow(-1);

        // put the date in if it is the first date or it is changed from the previous date
        td = tr.insertCell(-1);
        td.style.width = columnWidths[0] + columnWidthsMetric;
        td.innerHTML = "";
        
        // create a date object for the airing
        var d = new Date();
        d.setTime(airing.StartTime);

        // Time
        td.innerHTML += "<div class=" + timeClassName + ">" + getTimeString(d) + "</div>";

        // shade the background differently if it is a new date
        v = airing.StartTime;
        if (v >= _rrMgr.midnightNthDay(midnightIndex) || v < _rrMgr.midnightNthDay(midnightIndex - 1))
        {
            background = (background == 0) ? 1 : 0;
            
            td.innerHTML += "<div class=" + dateClassName + ">" + getDateString(d) + "</div>";
            theDate = d;
            
            while(v >= _rrMgr.midnightNthDay(midnightIndex))
            {
                midnightIndex++;
            }
            
            while(v < _rrMgr.midnightNthDay(midnightIndex - 1))
            {
                midnightIndex--;
            }
        }
        
        tr.style.backgroundColor = (background == 0) ? "#ffffff" : "#f0f0f0";
        td.className = (background == 0) ? tdClassName : tdClassNameShaded;
        
        // Episode Name and Description
        td = tr.insertCell(-1);
        td.style.width = columnWidths[2] + columnWidthsMetric;
        td.className = (background == 0) ? tdClassName : tdClassNameShaded;
        
        var epDescription = "";
        if (episode.Description != null)
        {
            epDescription = elipseText(episode.Description, _maxSummaryLength.value);
            
            if (epDescription.length < episode.Description.length)
            {
                epDescription += " <a href=\"" + _airingUrl.value + "?progId=" + episode.ProgramID + "&title=" + episode.Title + "\">" +
                                        "Full Summary" + 
                                 "</a>";                                    
            }
        }
        
        var epTitle = "";
        var titleAttrib = "";
        var newText = "";
        
        var maxTitleLength = _maxTitleLength.value;
        
        // determine if NEW! needs to be appended
        if (_futureEpisodeWmids != null)
        {
            for(var j = 0; j < _futureEpisodeWmids.length; ++j)
            {
                if (episode.ProgramID == _futureEpisodeWmids[j] &&
                    d.getYear() == _futureEpisodeDates[j].getYear() &&
                    d.getMonth() == _futureEpisodeDates[j].getMonth() &&
                    d.getDate() == _futureEpisodeDates[j].getDate())
                {
                    newText = "<div class=\"tsno_newepisode\" id=\"tsno_newepisode\">NEW!</div>"
                    maxTitleLength = _maxTitleLength.value - 5
                }
            }
        }
        
        if (episode.EpisodeTitle != null)
        {
            // show a tool tip if episode title has been cut off
            epTitle = elipseText(episode.EpisodeTitle, maxTitleLength);
            
            if (epTitle.length < episode.EpisodeTitle.length)
            { 
                titleAttrib = "title=\"" + episode.EpisodeTitle + "\" alt=\"" + episode.EpisodeTitle + "\"";
            }
            else
            {
                titleAttrib = "";
            }
        }
        else
        {
            epTitle = episode.Title;
        }
        
        // Add (Movie) to the end of titles of airings that are movies
        if (episode.Categories != null && episode.Categories.lastIndexOf("Movies:") != -1)
        {
            epTitle += " (Movie)";
        }
        
        td.innerHTML = "<div class=\"tvUpcomingAirings_titleLinks\">" + 
                            "<a class=\"tvUpcomingAirings_episodeTitleLink\"" + titleAttrib +
                               "href=\"" + _airingUrl.value + "?progId=" + episode.ProgramID + "&title=" + episode.Title + "\">" + 
                                epTitle +
                            "</a>" + newText +
                        "</div>" + 
                        "<div class=\"tvUpcomingAirings_descriptionText\">" + 
                            epDescription + 
                        "</div>";
                        
        // Channel and Call Letters
        td = tr.insertCell(-1);
        td.style.width = columnWidths[3] + columnWidthsMetric;
        td.className = (background == 0) ? tdClassName : tdClassNameShaded;
        if (_rrMgr.getHeadendIsDefault())
        {
            if (airing.Affiliate == null || airing.Affiliate == "")
            {
                if (airing.CallLetters != null && airing.CallLetters != "")
                {
                    td.innerHTML = airing.CallLetters;
                }
                else
                {
                    td.innerHTML = "N/A";
                }
            }
            else
            {
                td.innerHTML = airing.Affiliate;
            }
        }
        else
        {
            td.innerHTML =  airing.CallLetters + " " + airing.Channel;
            if (airing.Affiliate != null && airing.Affiliate != "")
            {
                td.innerHTML += "<br>(" + airing.Affiliate + ")";
            }
        }
        
        d = td = tr = null; 
    }
    _tableDiv.appendChild(table);
    
    // render pagination
    renderFooter()
    
    // clear date object
    theDate = null;
}

function renderHeader(table)
{
    var tr, td;

    // Column Header
    tr = table.insertRow(-1);
    
    tr.style.backgroundColor = "#bbbbbb";
    tr.className = trClassName;
    
    // Date
    td = tr.insertCell(-1);
    td.style.width = columnWidths[0] + columnWidthsMetric;
    td.className = headerDateTdClassName;
    td.innerHTML = "<a href=\"javascript:changeSortByValue('date')\">Date & Time</a>";
    if (_sortBy == "date") 
    {
        td.className = selectedDateTdClassName;
        if (_sortDir == 1)
        {
            td.innerHTML += "<img id='ua_dateimg' src='" + _ascendingImgSrc.value + "' onclick=\"changeSortByValue('date')\">";
        }
        else
        {
            td.innerHTML += "<img id='ua_dateimg' src='" + _descendingImgSrc.value + "' onclick=\"changeSortByValue('date')\"/>";
        }
    }
    else
    {
        td.innerHTML += "<img id='ua_dateimg' style='display: none;' src='" + _ascendingImgSrc.value + "' onclick=\"changeSortByValue('date')\">";
    }

    // Episode Name
    td = tr.insertCell(-1);
    td.style.width = columnWidths[2] + columnWidthsMetric;
    td.className = headerTdClassName;
    td.innerHTML = "<a href=\"javascript:changeSortByValue('episodename')\">Episode Name</a>";
    if (_sortBy == "episodename") 
    {
        td.className = selectedTdClassName;
        if (_sortDir == 1)
        {
            td.innerHTML += "<img id='ua_episodenameimg' src='" + _ascendingImgSrc.value + "' onclick=\"changeSortByValue('episodename')\">";
        }
        else
        {
            td.innerHTML += "<img id='ua_episodenameimg' src='" + _descendingImgSrc.value + "' onclick=\"changeSortByValue('episodename')\"/>";
        }
    }
    else
    {
        td.innerHTML += "<img id='ua_episodenameimg' style='display: none;' src='" + _ascendingImgSrc.value + "' onclick=\"changeSortByValue('episodename')\">";
    }
    
    // Channel
    td = tr.insertCell(-1);
    td.style.width = columnWidths[3] + columnWidthsMetric;
    td.className = headerTdClassName;
    var columnName;
    if (_rrMgr.getHeadendIsDefault())
    {
        columnName = "Network";
    }
    else
    {
        columnName = "Channel";
    }
    td.innerHTML = "<a href=\"javascript:changeSortByValue('channel')\">" + columnName + "</a>";
    if (_sortBy == "channel") 
    {
        td.className = selectedTdClassName;
        if (_sortDir == 1)
        {
            td.innerHTML += "<img id='ua_channelimg' src='" + _ascendingImgSrc.value + "' onclick=\"changeSortByValue('channel')\">";
        }
        else
        {
            td.innerHTML += "<img id='ua_channelimg' src='" + _descendingImgSrc.value + "' onclick=\"changeSortByValue('channel')\"/>";
        }
    }
    else
    {
        td.innerHTML += "<img id='ua_channelimg' style='display: none;' src='" + _ascendingImgSrc.value + "' onclick=\"changeSortByValue('channel')\">";
    }
}

function renderFooter()
{
    _paginationDiv.style.display = "block";
    
    // "x-y of z" element
    _boundsDiv.innerHTML = _lowerBound + "-" + _upperBound + " of " + _airingsFound;
    
    // max per page select box
    var html = "<div class=\"tvPagination_maxPerPageText\">" + 
                  "Per Page" + 
               "</div>" + 
                   "<select class=\"tvPagination_maxPerPageDropDown\"" + 
                          " onchange=\"changeMaxPerPage(this.value)\">"; 
    for (var i = 10, d = 0; i <= 40; i = i + 5 + d, d = d + 5)
    {
        html += "<option value=\"" + i + "\"";
        if (_maxAiringsPerPage == i)
        {
            html += " selected";
        }
        html += ">" + i + "</option>";
    }
    
    html += "</select>";
    _maxPerPageDiv.innerHTML = html;
    
    // page links
    _pageChooserDiv.innerHTML = "";
    
       var currentPage = parseInt((_lowerBound - 1) / _maxAiringsPerPage) + 1;
       if ((_lowerBound - 1) % _maxAiringsPerPage != 0)
    {
        currentPage++;
    }
       
    var numPages =  currentPage + parseInt((_airingsFound - _lowerBound) / _maxAiringsPerPage);
    
    var newLowerBound;
        
    if ((_maxAiringsPerPage * currentPage) < _airingsFound)
    {    
        // Next Page Link and Image
        newLowerBound = _lowerBound + parseInt(_maxAiringsPerPage);
        
        _pageChooserDiv.innerHTML += "<a class=\"tvPagination_arrowLink\"" + 
                                      " href=\"javascript:changeBounds(" + newLowerBound + ")\">" + 
                                        "Next >" + 
                                     "</a>";
    }
                        
    // display the pages surrouding the current page for navigation             
    var numPagesShown = 5;
    if (numPagesShown > numPages) numPagesShown = numPages;
    
    // only show the pages links if there is more than one page
    if (numPages > 1)
    {
        var startPage, endPage;
        startPage = currentPage - parseInt(numPagesShown/2);
        if (startPage < 1) 
        {
            startPage = 1;
        }
        endPage = startPage + numPagesShown - 1;
        if (endPage > numPages) 
        {
            endPage = numPages;
            startPage = endPage - numPagesShown + 1;
        }
        
        for (var i = endPage; i >= startPage; --i)
        {
            if (i == currentPage)
            {
                _pageChooserDiv.innerHTML += "<label class=\"tvPagination_pageLinkElemSelected\">" + 
                                                i + 
                                            "</label>";
            }
            else
            {
                newLowerBound = _lowerBound + _maxAiringsPerPage * (i - currentPage);
                if (newLowerBound < 1) newLowerBound = 1;
                
                _pageChooserDiv.innerHTML += "<a class=\"tvPagination_pageLinkElem\"" + 
                                                " href=\"javascript:changeBounds(" + newLowerBound + ")\">" + 
                                                    i + 
                                            "</a>";
            }
        }
            
        if (currentPage > 1)
        {
            // Previous Page Link and Image
            newLowerBound = _lowerBound - _maxAiringsPerPage;
            if (newLowerBound < 1) newLowerBound = 1;
            
            _pageChooserDiv.innerHTML += "<a class=\"tvPagination_arrowLink\"" + 
                                            "href=\"javascript:changeBounds(" + newLowerBound + ")\">" + 
                                            "< Back" + 
                                        "</a>";
        }
    }
}

/* Modification Functions */

function changeSortByValue(newSortBy)
{
    // if already selected, just switch the sort direction
    if (_sortBy == newSortBy)
    {
        _sortDir = -_sortDir;
    }
    else // change to new value and set sort direction to 0 (Ascending)
    {
        _sortBy = newSortBy;
        _sortDir = 1;
        
        // if primary is date, secondary is channel.  Otherwise, secondary is date
        if (_sortBy == "date")
        {
            _sortBy2 = "channel";
            _sortDir2 = 1;
        }
        else
        {
            _sortBy2 = "date";
            _sortDir2 = 1;
        }
    }
    
    // set lower bound back to 1
    _lowerBound = 1;
        
    // re-render the table
    renderResults();
}

function changeBounds(lower)
{
    // change the bounds
    _lowerBound = (lower < 1) ? 1 : lower;
    _upperBound = _lowerBound + (_maxAiringsPerPage - 1);
    
    // re-render the table
    renderResults();
}

function changeMaxPerPage(max)
{
    // change the max airings per page
    _maxAiringsPerPage = max;
    _upperBound = (_lowerBound + parseInt(_maxAiringsPerPage)) - 1;
    
    setCookie(_maxAiringsPerPageCookie, max);
    
    // re-render the table
    renderResults();
}

/* End Modification Functions */

// get all future airings indices (episode, airing) ordered as indicated by the sortBy and sortDir variables
function getNextAiringsIndices()
{
    var episode, airing;
    _airingsFound = 0;
    var nextAirings = new Array(_util_maxAiringsShown);
    var nextAiringsIndices = new Array(_util_maxAiringsShown);
    for (var i = 0; i < _util_maxAiringsShown; ++i)
    {
        nextAirings[i] = null;
        nextAiringsIndices[i] = new Array(2);
        nextAiringsIndices[i][0] = -1;
        nextAiringsIndices[i][1] = -1;
    }
    var currentTime = new Date();
    
    // used for ordering
    var maxi = -1;
    var maxj = -1;
    
    // take only a fraction of the airings if there are > _util_maxAiringsShown airings
    var skipFactor = 1;
    if (_allAirings.shows.length > _util_maxAiringsShown)
    {
        skipFactor = parseInt(_allAirings.shows.length / _util_maxAiringsShown);
    }
    
    for (var i = 0; i < _allAirings.shows.length; i=i+skipFactor)
    {
        episode = _allAirings.shows[i];
        
        if (!isValidEpisode(episode, _name.value)) continue;
        
        var airingIndicesArray = new Array(_util_maxAiringsShown);
        airingIndicesArray = getSortedAiringIndicesByStartTime(episode);
        
        var prevAiring = null;
        for (var j = 0; j < airingIndicesArray.length; j++)
        {
            if (airingIndicesArray[j] == -1) continue;
            
            // airing info
            airing = episode.Schedule[airingIndicesArray[j]];
                        
            if (isValidAiring(airing, prevAiring))
            {
                if (_airingsFound < _util_maxAiringsShown || 
                    compareAiringsUsingIndices(i, airingIndicesArray[j], maxi, maxj) == 1)
                {
                    // increment this if _airingsFound < _util_maxAiringsShown
                    if (_airingsFound < _util_maxAiringsShown)
                    {
                        _airingsFound++;
                    }

                    // insert airing into sorted arrays
                    insertAiringInArrays(nextAirings, nextAiringsIndices, airing, i, airingIndicesArray[j]);
                    
                    // set the current max airing indices
                    maxi = i;
                    maxj = airingIndicesArray[j];
                }
                prevAiring = airing;
            }
        }
    }
        
    nextAirings = null;
    
    return nextAiringsIndices;    
}

// return 1 if (i1, j1)  < (i2, j2)
//       -1 if (i1, j1)  > (i2, j2)
//   and  0 if (i1, j1) == (i2, j2)
// using the sortBy and sortDir variables
function compareAiringsUsingIndices(i1, j1, i2, j2)
{
    var air1, air2, ep1, ep2;
    
    // set up the episode and airing variables
    ep1 = _allAirings.shows[i1];
    ep2 = _allAirings.shows[i2];
    air1 = ep1.Schedule[j1];
    air2 = ep2.Schedule[j2];
    
    return compareAirings(ep1, ep2, air1, air2)
}

function compareAirings(ep1, ep2, air1, air2)
{
    var compA, compB;

    // set the appropriate compare values
    if (_sortBy == "date")
    {
        compA = air1.StartTime;
        compB = air2.StartTime;
    } 
    else if (_sortBy == "episodename")
    {
        compA = ep1.EpisodeTitle;
        compB = ep2.EpisodeTitle;
        if (compA == null) compA = ep1.Title;

        if (compB == null) compB = ep2.Title;
        
        compA = compA.toLowerCase();
        compB = compB.toLowerCase();
    }
    else if (_sortBy == "channel")
    {
        if (_rrMgr.getHeadendIsDefault())
        {
            compA = air1.Affiliate.toLowerCase();
            compB = air2.Affiliate.toLowerCase();
        }
        else
        {
            compA = air1.Channel;
            compB = air2.Channel;        
        }
    }
    
    // compare the values and return the appropriate number
    if (compA < compB) 
    {
        // return the sort direction
        return (_sortDir);
    } 
    else if (compA > compB)
    {
        // return the opposite of the sort direction
        return (-_sortDir);
    }
    else // if compA == compB, need to look at secondary sort value
    {
        // if two sorts are by the same value, return 0
        if (_sortBy == _sortBy2) return 0;
        
        // set to the secondary sortBy value
        var tempSortBy = _sortBy;
        var tempSortDir = _sortDir;
        _sortBy = _sortBy2;
        _sortDir = _sortDir2;
        
        // sort by the secondary sortBy value
        var retVal = compareAirings(ep1, ep2, air1, air2);
        
        // reset to the primary sortBy value
        _sortBy = tempSortBy;
        _sortDir = tempSortDir;
        
        return retVal;
    }
}

// insert airing and indices into sorted arrays
function insertAiringInArrays(airingArray, indicesArray, airing, index1, index2)
{
    // trying to insert something that doesn't belong simply return
    if ( (airingArray[_util_maxAiringsShown - 1] != null) && 
          compareAiringsUsingIndices(indicesArray[_util_maxAiringsShown - 1][0], 
                                     indicesArray[_util_maxAiringsShown - 1][1], 
                                     index1, 
                                     index2) == -1)
    {
        return;
    }
    
    // loop through and push back all the other ones along the way
    for (var i = _util_maxAiringsShown - 2; i >= 0; i--)
    {
        if (airingArray[i] != null && compareAiringsUsingIndices(indicesArray[i][0], 
                                                       indicesArray[i][1], 
                                                       index1, 
                                                       index2) == 1)
        {
            airingArray[i+1] = airing;
            indicesArray[i+1][0] = index1;
            indicesArray[i+1][1] = index2;
            return;
        }
        airingArray[i+1] = airingArray[i];
        indicesArray[i+1][0] = indicesArray[i][0];
        indicesArray[i+1][1] = indicesArray[i][1];
    }
    
    // array is empty, place at the front
    airingArray[0] = airing;
    indicesArray[0][0] = index1;
    indicesArray[0][1] = index2;
}