var currTimestamp = 0;
var currentCalendar = null;
var cookieIdentifier = null;
var isInitialRendering = true;
var myGamesInd = null;
var masterGamesArrayTemp = null;
var masterGamesArrayFinal = null;
var myGamesArray = null;
var log;
var timerId = 0;

function scoreboardsInitialPageLoad(path) 
{
    log = new logClass();
    log.create();

    ajaxGetNewFeed();

    setupPollingTimer(INTERVAL);
}

function setupPollingTimer(interval)
{
    // if setInterval was already done, clear it.
    if (timerId > 0)
        window.clearInterval(timerId);

    //log.write("Killed timer: " + timerId);

    ////log.write("Setting interval: " + interval);
    timerId = window.setInterval("ajaxGetNewFeed();", interval);
    //log.write("Set new timer: " + timerId);
}

function updateViewCastMiniscoreboard(scoreboardId, scoreboardName) {
	PATH = PATH_PREFIX + "/scoreboards/" + scoreboardId + PATH_SUFFIX;
	SCOREBOARD_ID = scoreboardId;
	var scoreboardNameElem = document.getElementById("scoreboardName");
	if (scoreboardNameElem)
		scoreboardNameElem.innerHTML = scoreboardName.toUpperCase();
	isInitialRendering = true;
	scoreboardsInitialPageLoad();
	createCookie(COOKIE_NAME, scoreboardId, 365);
}

function sendGamesToController(feedData, splitMe)
{
    var feedDataArray;

    if (splitMe)
        feedDataArray = stripInvalidRows(feedData.split(FEED_ROW_DELIMITER));
    else
        feedDataArray = stripInvalidRows(feedData);

    if (isInitialRendering)
    {
        if (METADATA)
        {
            processMetaData(feedDataArray[0]);
            feedDataArray.splice(0, DATA_INDEX);
        }
        
        dumpFeedDataArray(feedDataArray);
        
        buildMasterArrayTemp(feedDataArray);

        sortGameData();

        buildMasterArrayFinal();

        if (isViewcast)
        {
           buildViewCastGameAnchorCells(feedDataArray.length);
           feedDataArray = null;
           renderViewCastGames();
        }
        else
        {
            applyMyGamesFilter();

            dumpMasterGamesArray();
            buildGameAnchorCells(feedDataArray.length);
            feedDataArray = null;
            renderFullScoreboard();
        }
        isInitialRendering = false;
    }
    else 
    {
        if (isViewcast)
            processViewCastUpdate(feedDataArray);
        else
            processFeedUpdateRows(feedDataArray);
    }
}

function buildMasterArrayTemp(feedDataArray)
{
    var isMyGame;
    var singleGameString;
    var contestObj;

    ////log.write("PROCESSING STEP: buildMasterArrayTemp()");
    
    // instantiate global varible        
    // detailed comments below, on how the arrays are used 
    masterGamesArrayTemp = new Array(0);
            
    // Loop for each row in the FEED data file
    for (i = 0; i < feedDataArray.length; i++ )
    {    
        contestObj = populateContestFromString(feedDataArray[i]);        
        contestObj.isMyGame = 0; 

        ////log.write("Pushing data for contestID " + contestObj.contestID + " into masterGamesArrayTemp");
        
        masterGamesArrayTemp.push(contestObj);

        // after processing first game on the list, set cookie identifier.
        // TODO: make sure it replaces all '/' globally
        if (i == 0)
        {
        	var tempDate = contestObj.gameDateUrl;
            cookieIdentifier = "NCAAB_" + SCOREBOARD_ID + "_" + tempDate.replace(/\//g,"");
		}
        contestObj = null;
    }
    log.write("Cookie ID: " + cookieIdentifier);
}


function dumpFeedDataArray(feedDataArray)
{
    ////log.write("Dump of feedDataArray (before proccessing)..... array length is " + feedDataArray.length);
    
    // For each FEED file in the master list
    for (var i = 0; i < feedDataArray.length; i++ )
    {
        ////log.write(feedDataArray[i]);
    }
}


function sortGameData()
{
    ////log.write("PROCESSING STEP: sortGameData()");
    
    masterGamesArrayTemp.sort(function(a,b)
    {    
        var retVal;

        retVal = (a.gameState.gameOrder - b.gameState.gameOrder);        
        return retVal;
    })
}

function populateContestFromString(contestStr)
{
    var isInprogress = false;
    var isFinal = false;
    
    var masterRow = null;
    var contestObj = new Object();
    var tO = null;    
    var tk = null;
    var tStr = null;
    
    contestObj.rawFeed = contestStr;
    masterRow = contestStr.split(TOP_LEVEL_DELIMITER);

    if (masterRow.length < MASTER_ARRAY_LENGTH)
    {
        ////log.write("WARNING: Master Row appears to be missing some fields: " + masterRow.length);
    }   
    contestObj.contestID   = trimString(masterRow[CONTEST_ID]);
    contestObj.vendorContestID   = trimString(masterRow[STATSINC_CONTEST_ID]);
    contestObj.seasonYear  = trimString(masterRow[SEASON_YEAR]);
    contestObj.stageID     = trimString(masterRow[STAGE_ID]);
    contestObj.substageID  = trimString(masterRow[SUBSTAGE_ID]);
    contestObj.statusInd   = trimString(masterRow[STATUS]);
    contestObj.gameDateUrl = trimString(masterRow[DATE_URL]);
    contestObj.gameDateStr = trimString(masterRow[DATE_STR]);

    if (contestObj.gameDateStr.indexOf("TBD") == -1)
        contestObj.gameDateStr = contestObj.gameDateStr + " ET";

    // Set all flags associated with game status
    if (contestObj.statusInd == "" || contestObj.statusInd == "PRE" || contestObj.statusInd == "SCHE")
    {
        contestObj.isPregame = true;
        contestObj.isFinal = false;
        contestObj.isInprogress = false;
    }
    else if (contestObj.statusInd == "SUSP" || contestObj.statusInd == "CANC" || contestObj.statusInd == "FINA")
    {
        contestObj.isPregame = false;
        contestObj.isFinal = true;
        contestObj.isInprogress = false;
    }
    // this leaves out PROG, END- and DELA status
    else 
    {
        contestObj.isPregame = false;
        contestObj.isFinal = false;
        contestObj.isInprogress = true;
    }
    
    // GAMESTATE
    tStr = trimString(masterRow[GAMESTATE]);
    
    if (tStr != null && tStr != "")
    {
        tk = tStr.split(SECOND_LEVEL_DELIMITER);
        tO = parseGamestate(tk);
        tk = null;
        tStr = null;
        contestObj.gameState = tO;
        tO = null;
    }

    // VENUE
    tStr = trimString(masterRow[VENUE]);
    
    if (tStr != null && tStr != "")
    {
        tO = new Object();
        tk = tStr.split(SECOND_LEVEL_DELIMITER);
        tO.stadium = trimString(tk[STADIUM]);
        tO.city = trimString(tk[CITY]);
        tO.state = trimString(tk[STATE]);
        
        tk = null;
        tStr = null;
        if (tO.stadium == "" && tO.city == "")
            tO = null;
        contestObj.venue = tO;
        tO = null;
    }
    
    // LINKS
    tStr = trimString(masterRow[LINKS]);
    if (tStr != null && tStr != "")
    {
        tO = new Object();
        tk = tStr.split(SECOND_LEVEL_DELIMITER);
        tO.previewInd = trimString(tk[PREVIEW]);
        tO.boxscoreInd = trimString(tk[BOXSCORE]);
        tO.recapInd = trimString(tk[RECAP]);
	 tO.gameblogInd = trimString(tk[GAMEBLOG]);
	 tO.ticketcityurl = tk[TICKETCITY];
        
        tk = null;
        tStr = null;
        contestObj.links = tO;
        tO = null;
    }
    
    // HOME TEAM
    tStr = trimString(masterRow[HOME_TEAM]);
    if (tStr != null && tStr != "")
    {
        tk = tStr.split(SECOND_LEVEL_DELIMITER);
        tO = parseTeamInfo(tk);
        tk = null;
        tStr = null;
        contestObj.homeTeam = tO;
        tO = null;
    }
    
    // VISITING TEAM
    tStr = trimString(masterRow[VSTR_TEAM]);
    if (tStr != null && tStr != "")
    {
        tk = tStr.split(SECOND_LEVEL_DELIMITER);
        tO = parseTeamInfo(tk);
        tk = null;
        tStr = null;
        contestObj.visitingTeam = tO;    
        tO = null;
    }    

    // remove leaders if game is NOT in pregame state, and leader stats contain "." 
    //  (which means they are season stats)
    if (contestObj.isPregame == false)
    {
        if (contestObj.homeTeam.pointsLeader != null && contestObj.homeTeam.pointsLeader.stat.indexOf(".") > -1)
	    contestObj.homeTeam.pointsLeader = null;
        if (contestObj.homeTeam.reboundsLeader != null && contestObj.homeTeam.reboundsLeader.stat.indexOf(".") > -1)
	    contestObj.homeTeam.reboundsLeader = null;
        if (contestObj.homeTeam.assistsLeader != null && contestObj.homeTeam.assistsLeader.stat.indexOf(".") > -1)
	    contestObj.homeTeam.assistsLeader = null;
        if (contestObj.visitingTeam.pointsLeader != null && contestObj.visitingTeam.pointsLeader.stat.indexOf(".") > -1)
	    contestObj.visitingTeam.pointsLeader = null;
        if (contestObj.visitingTeam.reboundsLeader != null && contestObj.visitingTeam.reboundsLeader.stat.indexOf(".") > -1)
	    contestObj.visitingTeam.reboundsLeader = null;
        if (contestObj.visitingTeam.assistsLeader != null && contestObj.visitingTeam.assistsLeader.stat.indexOf(".") > -1)
	    contestObj.visitingTeam.assistsLeader = null;
    }

    // POST SEASON REGION NAME
    tStr = trimString(masterRow[POST_SESN_REGION]);
    if (tStr != null && tStr != "")
    {
        contestObj.region = tStr;
        tStr = null;
    }
    else
        contestObj.region = null;

    // SUBSTAGE NAME THAT IS ONLY NEEDED IN POSTSEASON
    tStr = trimString(masterRow[SUBSTAGE_NM]);
    if (tStr != null && tStr != "")
    {
        contestObj.substageName = tStr;
        tStr = null;
    }
    else
        contestObj.substageName = null;

    return contestObj;
}

function parseGamestate(tk)
{
    tO = null;

    if (tk.length > 0)
    {
        tO = new Object();

        tO.gameOrder     = trimString(tk[GAME_ORDER]);
        tO.clock         = trimString(tk[CLOCK]);
        tO.period        = trimString(tk[PERIOD]);
        tO.activeInd     = trimString(tk[ACTIVE]);

        //log.write("Possession team: " + tO.possInd + ", ballOnTeam: " + tO.ballonInd);
        if (tO.period == "1" && (tO.activeInd == "F" || tO.clock == "0:00"))
             tO.isHalftime = true;
        else
             tO.isHalftime = false;
    }
    return tO;
}

// return complete team object with leaders and linescore and next game information
function parseTeamInfo(st)
{
    var teamObj = new Object();
    var tO = null;
    var tStr = null;
    var tk = null;
    var hasStats = false;
    
    teamObj.id         = trimString(st[TEAM_ID]);

    tStr = trimString(st[VENDOR_ID]);
    if (tStr != null && tStr != "")
    {
        teamObj.vendorID = tStr;
        tStr = null;
    }
    else
    {
        teamObj.vendorID = teamObj.id;
    }

    teamObj.name       = trimString(st[TEAM_NAME]);
    teamObj.nickname   = trimString(st[TEAM_NICKNAME]);
    teamObj.urlName    = trimString(st[TEAM_URL]);
    teamObj.abrv       = trimString(st[TEAM_ABRV]);
    teamObj.totalScore = trimString(st[TOTAL_SCORE]);
    teamObj.wins       = trimString(st[WINS]);
    teamObj.losses     = trimString(st[LOSSES]);       

    if (teamObj.nickname == null || teamObj.nickname == "")
        teamObj.nickname = teamObj.name;

    tStr = null;
    tk = null;
		
		var leaderMap = new Object();
		leaderMap[PTSLDR] = "pointsLeader";
		leaderMap[RBNDLDR] = "reboundsLeader";
		leaderMap[ASSTLDR] = "assistsLeader";
		leaderMap[PTSLDR1] = "pointsLeader1";
		leaderMap[PTSLDR2] = "pointsLeader2";
		leaderMap[PTSLDR3] = "pointsLeader3";

		for (var index in leaderMap) {
			tStr = trimString(st[index]);
			if (tStr != null && tStr != "") {
					tO = new Object();
					tk = tStr.split(THIRD_LEVEL_DELIMITER);
					tO.id       = tk[LDR_ID];
					tO.name     = tk[LDR_NM];
					tO.linkable = tk[LDR_LINK];        
					tO.position = tk[LDR_POS];
					tO.stat     = tk[LDR_STAT];
					
					tStr = null;
					tk = null;
					// the assumption here is that there are always "leaders", even if stats are zero, so we need to filter those out.
					if (tO.name == "" || tO.stat == "" || tO.stat == "0" || tO.stat == "0.0")
							tO = null;
					teamObj[leaderMap[index]] = tO;
					tO = null;
			}
		}

    tStr = trimString(st[DIV_ID]);
    if (tStr != null && tStr != "")
    {
        teamObj.divisionId = tStr;    

       if (teamObj.divisionId == 'divia')
           teamObj.linkable = true;
       else
           teamObj.linkable = false;
    }

    tStr = trimString(st[CONF_ID]);
    if (tStr != null && tStr != "")
        teamObj.conferenceId = tStr;    

    tStr = trimString(st[AP_RANK]);
    if (tStr != null && tStr != "")
    {
        if (tStr == "0")
            tStr = "";
        else if (parseInt(tStr) > 25)
        	tStr = "";
        teamObj.apRank = tStr;    
    }
    
    return teamObj;
}

function buildMasterArrayFinal()
{
    var contestObj;

    masterGamesArrayFinal = new Array(0);
    
    for (i = 0; i < masterGamesArrayTemp.length; i++) 
    {
        contestObj = masterGamesArrayTemp[i];

        masterGamesArrayFinal.push(contestObj);
        contestObj = null;            
    }
    masterGamesArrayTemp = null;
}


function applyMyGamesFilter() 
{
    var selectedGamesArray;
    var myContestID;
    var rowIndex;
    var newFirstRow;
    var rowToCopyFrom;

    selectedGamesArray = getMyGamesFromCookie(); 
        
    for (var i = selectedGamesArray.length - 1; i >= 0; i--) 
    {
        myContestID = selectedGamesArray[i];

        rowIndex = getRowNumFromGameId(myContestID);
        if (rowIndex != null) 
        {
            // copy object into a new holder
            newFirstRow = masterGamesArrayFinal[rowIndex];

            // set myGame flag
            newFirstRow.isMyGame = 1;

            // push copied object in the beginning of the array
            masterGamesArrayFinal.unshift(newFirstRow);

            // find new index for old game location
            rowToCopyFrom = rowIndex + 1;
            
            // cut it out
            masterGamesArrayFinal.splice(rowToCopyFrom, 1);
        }
    }            
    selectedGamesArray = null;
}


function getRowNumFromGameId(myContestID) 
{
    for (var i = 0; i < masterGamesArrayFinal.length; i++) 
    {
        if (masterGamesArrayFinal[i].contestID == myContestID) 
        {
            ////log.write(".... found contestID in row number " + i);
            return i;
        }
    }
    return null;
}


function dumpMasterGamesArray() 
{
    var contestObj;
    
    for (i = 0; i < masterGamesArrayFinal.length; i++)
    {    
        contestObj = masterGamesArrayFinal[i];
        contestObj = null;
    }
}

function setSpecialFlags(oldO, newO)
{
    // Find if anyone has new scores. If scores haven't changed, reset.
    // The games that haven't changed at all won't be processed, so until they are, new score flag will stay same.
    // This logic might be faulty, TODO: verify
    if (! (newO.isFinal || newO.isActiveInd == "false" || newO.homeTeam.totalScore == "" || oldO.homeTeam.totalScore == "") &&
        ! (newO.homeTeam.totalScore == "0") &&
        newO.homeTeam.totalScore != oldO.homeTeam.totalScore)
        newO.homeTeam.isNewScore = true;
    else
        newO.homeTeam.isNewScore = false;
    if (! (newO.isFinal || newO.isActiveInd == "false" || newO.visitingTeam.totalScore == "" || oldO.visitingTeam.totalScore == "") &&
        ! (newO.visitingTeam.totalScore == "0") &&
        newO.visitingTeam.totalScore != oldO.visitingTeam.totalScore)
        newO.visitingTeam.isNewScore = true;
    else
        newO.visitingTeam.isNewScore = false;

    // reset possession indicator when game is inactive
    if (newO.isFinal || newO.gameState.isHalftime)
        newO.gameState.possInd = "";
    
    return newO;
}


function processFeedUpdateRows(feedDataArray)
{
    var feedRow;
    var fieldArray;
    var domIdSequence;
    var newContestObj;
    var oldContestObj;
    var contestID;

    var tempFeedDataArray = feedDataArray.slice(0,feedDataArray.length);
    log.write("Temp FeedDataArray length: " + tempFeedDataArray.length +
             ", FeedDataArray length: " + feedDataArray.length);
    ////log.write("PROCESSING STEP: processFeedUpdateRows()");

    // is it a freshly updated file, or cached one.
    if (METADATA)
    {
        if (processMetaData(feedDataArray[0]) == false)
            return;
        feedDataArray.splice(0, DATA_INDEX);
    }

    // if there is a difference in size between old and new feed array, that means
    // there were deleted games or added games. We need to force reload the entire page.
    if (feedDataArray.length != masterGamesArrayFinal.length)
    {
        isInitialRendering = true;
        sendGamesToController(tempFeedDataArray, false);
        return;
    }

    for (i = 0; i < feedDataArray.length; i++)
    {
        feedRow = trimString(feedDataArray[i]);

        ////log.write("processing data row (is it an Update row?): " + feedRow);

        fieldArray = feedRow.split(TOP_LEVEL_DELIMITER);

        contestID = trimString(fieldArray[CONTEST_ID]);

        ////log.write("Processing updated feed data for contestID " + contestID);

        for (j = 0; j < masterGamesArrayFinal.length; j++) 
        {            
            if (masterGamesArrayFinal[j].contestID == contestID) 
            {                
                ////log.write("Found match in master Array.... rendering game with updated data");
                
                oldContestObj = masterGamesArrayFinal[j];
                newContestObj = populateContestFromString(feedRow);        
                
                // TODO: find out why it thinks they are always different
                if (oldContestObj.rawFeed != newContestObj.rawFeed)
                {
                    ////log.write("Contests are different,  updating!");
                    newContestObj = setSpecialFlags(oldContestObj, newContestObj);
                    masterGamesArrayFinal[j] = newContestObj;
                    
                    domIdSequence = j + 1;                
                    
                    buildMiniscoreboard(domIdSequence, masterGamesArrayFinal[j]);
                }            
                else
                {
                    ////log.write("Contest doesn't need updating, skip!");
                    ////log.write(newContestObj.rawFeed);
                    //log.write(oldContestObj.rawFeed);
                }
                break;
            }        
        }        
        fieldArray = null;
    }
}


function processViewCastUpdate(feedDataArray)
{
    var feedRow;
    var fieldArray;
    var domIdSequence;
    var newContestObj;
    var oldContestObj;
    var contestID;

    var tempFeedDataArray = feedDataArray.slice(0,feedDataArray.length);
    //var tempFeedDataArray = feedDataArray;
    if (METADATA)
    {
        if (processMetaData(feedDataArray[0]) == false)
            return;
        feedDataArray.splice(0, DATA_INDEX);
    }

    // if there is a difference in size between old and new feed array, that means
    // there were deleted games or added games. We need to force reload the entire page.
    if (feedDataArray.length != masterGamesArrayFinal.length)
    {
        isInitialRendering = true;
        sendGamesToController(tempFeedDataArray, false);
        return;
    }

    for (i = 0; i < feedDataArray.length; i++)
    {
        feedRow = trimString(feedDataArray[i]);
        fieldArray = feedRow.split(TOP_LEVEL_DELIMITER);

        contestID = trimString(fieldArray[CONTEST_ID]);

        for (j = 0; j < masterGamesArrayFinal.length; j++)
        {
            if (masterGamesArrayFinal[j].contestID == contestID)
            {
                oldContestObj = masterGamesArrayFinal[j];
                newContestObj = populateContestFromString(feedRow);

                if (oldContestObj.rawFeed != newContestObj.rawFeed)
                {
                    newContestObj = setSpecialFlags(oldContestObj, newContestObj);
                    masterGamesArrayFinal[j] = newContestObj;

                    domIdSequence = j + 1;

                    buildViewCastMiniscoreboard(domIdSequence, masterGamesArrayFinal[j]);
                }
                else
                {
                    ////log.write(oldContestObj.rawFeed);
                }
                break;
            }
        }
        fieldArray = null;
    }
}


function renderFullScoreboard() 
{    
    var domIdSequence;
    var gameTime;
    var isMyGame;
    var feedData;

    ////log.write("PROCESSING STEP: renderFullScoreboard()");

    for (var i = 0; i < masterGamesArrayFinal.length; i++) 
    {
        domIdSequence = i + 1;

        gameTime = masterGamesArrayFinal[i].dateString;
        isMyGame = Number(masterGamesArrayFinal[i].isMyGame);
        ////log.write("Rendering Game for domIdSequence: " + domIdSequence);

        buildMiniscoreboard(domIdSequence, masterGamesArrayFinal[i]);
    }
}

function backToScoreboard() 
{
    buildGameAnchorCells(masterGamesArrayFinal.length);
        
    // Resetting timer after updating games
    setupPollingTimer(INTERVAL);

    renderFullScoreboard();
}

function newScoreboardAfterMyGamesSelected() 
{
    applyMyGamesFilter();

    buildGameAnchorCells(masterGamesArrayFinal.length);

    // Resetting timer after updating games
    setupPollingTimer(INTERVAL);
        
    renderFullScoreboard();
}

function renderViewCastGames()
{
    var domIdSequence;
    var gameTime;
    var feedData;

    for (var i = 0; i < masterGamesArrayFinal.length; i++)
    {
        domIdSequence = i + 1;
        gameTime = masterGamesArrayFinal[i].dateString;
        buildViewCastMiniscoreboard(domIdSequence, masterGamesArrayFinal[i]);
    }
}

