/*
This file contains definitions of the 
DataTable and DataTableManager objects. 
*/

var sid = request.getParameter("sid");
var cid = request.getParameter("gid");
var lid = request.getParameter("lid");
var pos = request.getParameter("pos");
var playerBio ;
var playerAwards;
var rawLastBatting;
var rawLastPitching;
var rawCareerBatting;
var rawCareerPitching;
var rawBatting;
var rawPitching;
var rawSplitBatting;
var rawSplitPitching;
var rawWinPitching;
var rawWinBatting;
var lookupUrlJSON = "/lookup/json/";
var lookupUrlXML  = "/lookup/xml/";
var season = "2011";
var gameType = 'R';


if (sid == null || sid == "null") {
    sid = "milb";
}

// used to get the current EST time.  Used by scoreboard and other
// places to know "today".  param offset optional number of hours from
// 'now' to offset the time.  Used to cause "today" to start at
// something like 8am (-8 offset) much like the daystart param in the
// date taglib.
function getNowDate(offset) {
    var timeStart;
    if (offset) { 
        return new Date(currentTimeMillis + (1000 * 60 * 60 * offset));
    } else {
        return new Date(currentTimeMillis);
    }

}
  

/////////// BEGIN DATATABLE OBJECT SCRIPTS ///////////

var DT_SORT_ASC  = 0;
var DT_SORT_DESC = 1;
var DT_NO_SORT   = 2;

var DT_LEFT   = "left";
var DT_RIGHT  = "right";
var DT_CENTER = "center";

var DT_MLB_CLUB_IDS=",108,109,110,111,112,113,114,115,116,117,118,119,120,121,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,158,"

function DataTable(data, colMetadata, initialSortColCode, tableTitle) {

    // ensure that params are valid:
    if (data.length>0) {
        /*
        if (data[0].length!=colMetadata.length) {
            alert("Error constructing DataTable: colMetadata array must have same number of elements as interior data-array elements(data[0].length="+data[0].length+"; colMetadata.length="+colMetadata.length+").")
            return;
        }
        */
    }

    // constructor values:
    this.data = data; 
    this.tableTitle = tableTitle;
    this.initialSortColCode = initialSortColCode;
    this.currentSortColCode = initialSortColCode;
    this.divId = null;
    
    this.currentHighlighedIdx = -1;
    
    this.suppressTitleBar  = false;
    this.suppressHeaderRow = false;
    // handling col metadata as arrays instead of in a more "elegant" way for performance reasons:
    this.colCodes = [];
    this.displayNames = [];
    this.sortTypes = [];
    this.visibilities = [];
    this.sortFunctionNames = [];
    this.altColsForSort = [];
    this.rowSuppressionCheckFunctionNames = [];
    this.colWidths = [];
    this.colAligns = [];
    for (var i=0; i<colMetadata.length; i++) {
        this.colCodes[i] = colMetadata[i][0];
        this.displayNames[i] = colMetadata[i][1];
        this.sortTypes[i] = colMetadata[i][2];
        this.visibilities[i] = colMetadata[i][3];
        this.sortFunctionNames[i] = colMetadata[i][4];
        this.altColsForSort[i] = colMetadata[i][5];
        this.rowSuppressionCheckFunctionNames[i] = colMetadata[i][6];
        this.colWidths[i] = colMetadata[i][7];
        this.colAligns[i] = colMetadata[i][8];
    }

    this.tableManagerIdx; // set by DataTableManager

    // methods:
    this.sort = _DataTable_sort;
    this.displaySortedOn = _DataTable_displaySortedOn;
    this.getColIdxFromColCode = _DataTable_getColIdxFromColCode;
    this.write = _DataTable_write;
    this.writePleaseWait = _DataTable_writePleaseWait;
    this.getTableHTML = _DataTable_getTableHTML;
    this.writeTableContainer = _DataTable_writeTableContainer;
    this.writePlayerTableContainer = _DataTable_writePlayerTableContainer;
    this.doHighlightRow = _doHighlightRow;
    
    // sort on initial sort col:
    if (initialSortColCode != null) {
        this.sort(initialSortColCode);
    }
}

function _getNumber(str) {
    var okChars = "-1234567890.";
    var ret = "";
    for (var i=0; i<str.length; i++) {
        var thisChar = str.charAt(i)
        if (okChars.indexOf(thisChar)>-1) {
            ret += thisChar;
        }
    }
    if (str == "") {
        return 0;
    }
    return parseFloat(str);
}

function _getObject(objId) {
    var doc = document;
    if (doc.getElementById) {
        return doc.getElementById(objId);
    }
    if (doc.all[objId]) {
        return doc.all[objId];
    }
    return null;    
}

function _DataTable_writePleaseWait(targetObjId) {
    var targetObj = _getObject(targetObjId);
    var msg = "<div align=\"left\"><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" class=\"dataTableClass\" style=\"background-color:#990000; color:#FFFFFF;\"><tr>";
    msg += "<td style=\"background-color:#990000; text-align:left; color:#FFFFFF; font-weight: bold;\">&nbsp;&nbsp;Please wait: sorting table...&nbsp;&nbsp;<br/></td>";
    msg += "</tr></table></div>";

    if (targetObj.insertAdjacentHTML) {
        targetObj.insertAdjacentHTML("afterBegin",msg);
    } else {
        try {
            var el = document.createElement("span");
            el.innerHTML = msg;
            targetObj.insertBefore(el, targetObj.firstChild);
        } catch(e) {
            targetObj.innerHTML = msg;
        }
    }
}

function _DataTable_write(targetObjId,flipOrderAfterSort) {
    var targetObj = _getObject(targetObjId);
    var tableHTML = this.getTableHTML(targetObjId,flipOrderAfterSort);
    var s = tableHTML.join(""); // build the table html from array contents
    targetObj.innerHTML = s;

    // attach event handlers to data tables to highlight rows
    var elements = targetObj.getElementsByTagName("table");
    for (var i = 0; i < elements.length; i++) {
        var el = elements[i];
        if (el.className == "dataTableClass") {
            if (typeof window.addEventListener != "undefined") {     // the firefox way
                el.addEventListener("mousedown", this.doHighlightRow, false);
            } else if (typeof window.attachEvent != "undefined") {   // the ie way
                el.attachEvent("onmousedown", this.doHighlightRow);
            }
        }
    }
}

// event handler for rowHighlighting
function _doHighlightRow(e) {
    if (!e) e = window.event;  // for IE
	var target = e.target || e.srcElement; // for IE
    var cell = target;
    var row = target;
    var rowId = target.id.substring(5); // store the row id so we can highlighed again after sort

    // go up the tree till we find the parent row
    while ((row.tagName != "TR") && row.parentNode) {
        row = row.parentNode;
    }

    if (row.className == "dataRow") {

        // go up the tree till we find the parent table
        while ((target.tagName != "TABLE") && (target.className != "dataTableClass") && target.parentNode) {
            target = target.parentNode;
        }
        if (target.className == "dataTableClass") {
            tableId = target.id.substring(6);
            DataTableManager.dataTables[tableId].currentHighlighedIdx = rowId; // store the id of the row to highlight

            var rows = target.getElementsByTagName("tr");
            for (var l=0; l < rows.length; l++) {
                if (rows[l].className == "highlightRow") {
                    rows[l].className = "dataRow";
                }
            }
        }
        row.className = "highlightRow";
    }
}

function _DataTable_writeTableContainer(divId, finalRowContents) {

    if (arguments.length == 1) {
        finalRowContents = null;
    }
    this.divId = divId;

    var tableHTML = this.getTableHTML(divId,false,finalRowContents);
    document.write("<div style=\"border:0px solid #000000; \" id="+divId+" class=\"divContainerClass\" >");
    var tLength = tableHTML.length;
    for (var i=0; i<tLength; i++) {
        if (!tableHTML[i]) {
            break;
        }
        document.write(tableHTML[i]);
    }
    document.write("</div>");

    var elements = document.getElementsByTagName("table");
    for (var i=0; i<elements.length; i++) {
        var el = elements[i];
        if (el.className == "dataTableClass") {
            if (typeof window.addEventListener != "undefined") {     // the firefox way
                el.addEventListener("mousedown", this.doHighlightRow, false);
            } else if (typeof window.attachEvent != "undefined") {   // the ie way
                el.attachEvent("onmousedown", this.doHighlightRow);
            }
        }
    }

}


function _DataTable_writePlayerTableContainer(divId, finalRowContents) {

    if (arguments.length == 1) {
        finalRowContents = null;
    }
    this.divId = divId;
	var containerHTML = "";
    var tableHTML = this.getTableHTML(divId,false,finalRowContents);
    containerHTML += "<div style=\"border:0px solid #000000; \" id="+divId+" class=\"divContainerClass\" >";
    var tLength = tableHTML.length;
    for (var i=0; i<tLength; i++) {
        if (!tableHTML[i]) {
            break;
        }
        containerHTML += tableHTML[i];
    }
    containerHTML += "</div>";
/**
    var elements = document.getElementsByTagName("table");
    for (var i=0; i<elements.length; i++) {
        var el = elements[i];
        if (el.className == "dataTableClass") {
            if (typeof window.addEventListener != "undefined") {     // the firefox way
                el.addEventListener("mousedown", this.doHighlightRow, false);
            } else if (typeof window.attachEvent != "undefined") {   // the ie way
                el.attachEvent("onmousedown", this.doHighlightRow);
            }
        }
    }*/
		
	return containerHTML;
}

function clubLink(linkLabel, clubId) {
    if (clubId == "0") {
        return "-";
    }
    if (isMajorLeagueClub(clubId)) {
        return "<a class=\"clubLink\" href=\"http://www.mlb.com/minors/milb_redirector.jsp?cid=t" + clubId + "\" target=\"_blank\">" + linkLabel + "</a>";
    } else {

        var linkedClub = "<a class=\"clubLink\" target=\"_parent\" href=\"/clubs/index.jsp?cid=t" + clubId + "\">" + linkLabel + "</a>";

        // if we've sourced in the properties js file and the club id
        // isnt defined, then dont link it.
        // 
        // we check for properties and default to linking for
        // backwards compatibility
        try { 
            if (properties) {
                var clubid = "t" + clubId;
                if (properties.clubs[clubid] && properties.clubs[clubid].hidden == "0") { 
                    return linkedClub;
                } else {
                    return linkLabel;
                }
            }
        } catch(e) {
            return  linkedClub;
        }

        return  linkedClub;

    }
}

function isMajorLeagueClub(clubId) {
    // note: DT_MLB_CLUB_IDS is a comma-delimited list of numeric MLB club
    // ids; its first and last char are also commas, so the following test
    // is always valid:
    return ((","+DT_MLB_CLUB_IDS+",").indexOf(clubId)>-1);
}


// note: anchor tag can have this format: 
// "<a href=\"#\" onclick=\"processBookmarkPlayer('~PLAYER_NAME~','~PLAYER_ID~'); return false;\">bookmark</a>"
// ...where ~ chars delimit column values to replace for this row.
// Note that the element must NOT already exist in the "rows" 2D array, but that the
// col MUST exist in the col metadata:
function addEndOfRowButtons(rows, anchorTag, colMetadata) {
    
    for (var i=0; i<rows.length; i++) {
        var row = rows[i];
        var parsedAnchorTag = "" + anchorTag;
        while (parsedAnchorTag.indexOf("~")>-1) {
            var firstIndexOf = parsedAnchorTag.indexOf("~");
            var nextIndexOf = parsedAnchorTag.indexOf("~", firstIndexOf+1);
            var colName = parsedAnchorTag.substring(firstIndexOf+1, nextIndexOf);
            var colValue = escapeQuotes(row[getIdxFromCode(colName, colMetadata)]);
            parsedAnchorTag = parsedAnchorTag.substring(0,firstIndexOf)+colValue+parsedAnchorTag.substring(nextIndexOf+1, parsedAnchorTag.length);
        }
        row[row.length] = parsedAnchorTag;
    }
}

function escapeQuotes(s) {
    var ret = "";
    for (var i=0; i<s.length; i++) {
        var c = s.charAt(i);
        if (c == "\'") {
            ret += "\\\'";
        } else if (c == "\"") {
            ret += "\\\"";
        } else {
            ret += c;
        }
    }
    return ret;
}

function getIdxFromCode(colName, colMetadata) {
    for (var i=0; i<colMetadata.length; i++) {
        if (colMetadata[i][0] == colName) {
            return i;
        }
    }
    return -1;
}

function addPlayerLinkToRow(row, playerNameIdx, playerIdIdx, playerPosIdx) {
    var playerPos = "";
    if (playerPosIdx >= 0) {
        playerPos = row[playerPosIdx];
    } else if (playerPosIdx == -1) {
        playerPos = "P";
    } else if (playerPosIdx == -2) {
        // indicates not-a-pitcher; this is all we care about for these purposes:
        playerPos = "";
    }

    if (sid==null || sid=="null") {
        sid = "milb";
    }

    aTag = "<a class=\"playerLink\" target=\"_parent\" href=\"/milb/stats/stats.jsp?pos="+playerPos+"&sid="+sid+"&t=p_pbp&pid="+row[playerIdIdx]+"\">"+row[playerNameIdx]+"</a>";
    row[playerNameIdx]=aTag;
}

function addClubLinks(rows, clubNameIdx, clubIdIdx) {
    for (var i=0; i<rows.length; i++) {
        var row = rows[i];
        var clubId = row[clubIdIdx];
        if (clubId!=null && clubId.length>0) {
            var clubName = row[clubNameIdx];
            // bold the current team name in stats
            if (("t" + clubId) == ((cid)?cid:sid)) {
                row[clubNameIdx] = "<!-- " + clubName + " --><span class=\"highlightTeam\">" + clubLink(clubName, clubId) + "</span>";
            } else {
                row[clubNameIdx] = "<!-- " + clubName + " -->" + clubLink(clubName, clubId);
            }
        }
    }
}

function addPlayerLinks(rows, playerNameIdx, playerIdIdx, playerPosIdx) {
    for (var i=0; i<rows.length; i++) {
        addPlayerLinkToRow(rows[i], playerNameIdx, playerIdIdx, playerPosIdx);
    }
}

function _countVisibleRows(visibilityBooleans) {
    var c = 0;
    for (var i=0; i<visibilityBooleans.length; i++) {
        c += (visibilityBooleans[i]?1:0);
    }
    return c;
}

// note: this function returns an array of strings since this increases performance compared to returning one big string
function _DataTable_getTableHTML(targetObjId,flipOrderAfterSort,finalRowContents) {

    if (arguments.length < 3) {
        finalRowContents = null;
    }
    var supressionFunctionName = "returnTrue";
    for (var i=0; i<this.rowSuppressionCheckFunctionNames.length; i++) {
        if (this.currentSortColCode==this.colCodes[i]) {
            if (this.rowSuppressionCheckFunctionNames[i]!=null) {
                supressionFunctionName=this.rowSuppressionCheckFunctionNames[i];
            }
            break;
        }
    }
    var supressionFunction=window[supressionFunctionName];
    var ret = new Array(this.data.length*this.colCodes.length*5);
    var retIdx = 0;
    var flipOrderAfterSortArg = flipOrderAfterSort;
    var s = "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" class=\"dataTableClass\" id=\"table_" + this.tableManagerIdx + "\">";
    
    if (!this.suppressTitleBar) {
        s += "<tr class=\"titleRow\">";
        s += "<td colspan=\"" + _countVisibleRows(this.visibilities) + "\">" + this.tableTitle + "</td>";
        s += "</tr>";
    }
    
    s += "<tr " + (this.suppressHeaderRow?"style=\"display:none;\"":"") + " class=\"headerRow\">";
    var methodCallPrefix="";
    for (var c=0; c<this.colCodes.length; c++) {
        if (this.visibilities[c]) {
            s += "<td style=\"text-align:center;\">";
            if (this.sortTypes[c]!=DT_NO_SORT) {
                if (this.currentSortColCode==this.colCodes[c]) {
                    flipOrderAfterSortArg=!flipOrderAfterSort;
                } else {
                    flipOrderAfterSortArg=false;
                }
                s += "<a class=\"headerLinkClass\" href=\"javascript:"+methodCallPrefix+"DataTableManager.dataTables["+this.tableManagerIdx+"].displaySortedOn('"+this.colCodes[c]+"','"+targetObjId+"',"+flipOrderAfterSortArg+")\">";
            }
            s += this.displayNames[c];
            if (this.sortTypes[c]!=DT_NO_SORT) {
                s += "</a>&nbsp;"; // added filler for cols w/o a header label
            }           
            s += "</td>";
        }
    }
    s += "</tr>";

    ret[retIdx] = s; retIdx++;
    var row;
    var initialIdx;
    var c;
    var cssClass;
    var isCurrentHighlightedRow;
    var dLength = this.data.length;
    var currColIdx = 0;
    for (var i=0; i<this.colCodes.length; i++) {
        if (this.colCodes[i]==this.currentSortColCode) {
            currColIdx = i;
            break;
        }
    }
	
    var isTotalIdx,isTotalRow = "";
    for (var i=0; i<this.colCodes.length; i++) {
        if (this.colCodes[i] == "IS_TOTAL") {
            isTotalIdx = i;
            break;
        }
    }
    var rowCount = 0;
    for (var i=0; i<dLength; i++) {
        row = this.data[i];
        if (!supressionFunction(row[currColIdx], row)) {
            // we're not displaying this row as sorted:
            continue;
        }
		
		if (isTotalIdx) {
        	isTotalRow = (this.data[i][isTotalIdx] == "Y");
		}
        isCurrentHighlightedRow = (this.data[i][0] == this.currentHighlighedIdx);
        initialIdx = this.data[i][0];
        var rowClass = "even";
        if (rowCount % 2) { rowClass = "odd"; }
        if (isCurrentHighlightedRow || isTotalRow) {
            ret[retIdx] = "<tr class=\"dataRow highlightRow " + rowClass + "\">\n\n"; 
            retIdx++;
        } else {
            ret[retIdx] = "<tr class=\"dataRow " + rowClass + "\">\n\n";
            retIdx++;
        }
        var rowShownFlag = false;
		
        for (c=0; c<this.colCodes.length; c++) {
            if (this.visibilities[c]) {
                cssClass = (this.currentSortColCode==this.colCodes[c]?"currSortDataCell":"dataCell");

                // need to move alignment to a class definition?
                ret[retIdx] = "<td id=\"cell_" + initialIdx + "\""
                + "align=\"" + this.colAligns[c] + "\" class=\"" + cssClass + "\" style=\"width:" + this.colWidths[c] + "px;\">"
//                + this.data[i][c]
                + (this.data[i][c]==""?"&nbsp;":this.data[i][c])
                + "</td>";

                retIdx++;
                rowShownFlag = true;
            }
        }
        if (rowShownFlag) { rowCount++; }
        if (isTotalRow) { rowCount=0; }
        ret[retIdx] = "</tr>\n\n"; 
        retIdx++
    }
    if (finalRowContents!=null) {
        ret[retIdx] = "<tr><td style=\"text-align:left; background-color: transparent;\" colspan=" + _countVisibleRows(this.visibilities) + ">" + finalRowContents + "</td></tr>"; 
        retIdx++
    }
    ret[retIdx] = "</table>"; 
    retIdx++;
    return ret;
}

function _DataTable_displaySortedOn(colCode,targetObjId,flipOrderAfterSort) {
    this.writePleaseWait(targetObjId);
    
    if (!flipOrderAfterSort) {
        this.sort(colCode);
    } else {
        // already sorted; just reversing order:
        this.data = this.data.reverse();
    }
    setTimeout("DataTableManager.dataTables["+this.tableManagerIdx+"].write('"+targetObjId+"',"+flipOrderAfterSort+")",100);
}

function _DataTable_getColIdxFromColCode(colCode) {
    for (var i=0; i<this.colCodes.length; i++) {
        if (this.colCodes[i] == colCode) {
            return i;
        }
    }
    return -1;
}

function _DataTable_sort(colCode) {
    this.currentSortColCode=colCode;
    var colIdx=this.getColIdxFromColCode(colCode);

    colCodeForSort=this.altColsForSort[colIdx];
    if (colCodeForSort==null) {
        colCodeForSort=colCode;
    }
    var colIdxForSort=this.getColIdxFromColCode(colCodeForSort);

    DataTableManager.currSortAscending=(parseInt(this.sortTypes[colIdx])==DT_SORT_ASC);
    DataTableManager.currSortColIndex=colIdxForSort;
    this.data.sort(window[this.sortFunctionNames[colIdx]]);
}

var dataTableLoaded = true;

/////////// END DATATABLE OBJECT SCRIPTS ///////////




/////////// BEGIN DATATABLEMANAGER OBJECT SCRIPTS ///////////

var managerInstanceInstantiated = false;

function _DataTableManager() {
    if (!window.requestLoaded) {
//        alert("To use DataTableManager, you must import Request.js first.")
        return null;
    }
    if (!window.dataTableLoaded) {
//        alert("To use DataTableManager, you must import DataTable.js first.")
        return null;
    }
    if (managerInstanceInstantiated) {
//        alert("_DataTableManager cannot be instantiated more than once; use the 'DataTableManager' instance.")
        return null;
    }
    this.dataTables=[]; // holds references to all DataTables
    this.getDataTable=_DataTableManager_getDataTable;
    this.copyArray=_DataTableManager_copyArray;
    this.reorderData=_DataTableManager_reorderData;
    this.reorderDataNew=_DataTableManager_reorderDataNew;

    // bit o non-object-orientation: these are set before every sort:
    this.currSortAscending=false;
    this.currSortColIndex=-1;
}

// * raw-data: 2-dim array of data
// * rawDataColNames: array of strings which are ordered col names in the raw data array
// * colMetadata: column metadata specified for each display type
function _DataTableManager_reorderData(rawData, rawDataColNames, colMetadata) {
    var orderedIdxToRawIdx = new HashMap();
    for (var i=1; i<colMetadata.length; i++) {
        var colName = colMetadata[i][0];
        var rawIdx = -1;
        for (var j=0; j<rawDataColNames.length; j++) {
            if (rawDataColNames[j] == colName) {
                rawIdx = j;
                orderedIdxToRawIdx.put(i, rawIdx);
                break;
            }
        }
        if (rawIdx == -1) {
            // okay; sometimes this will happen:
            //alert("col metadata specifies a col '"+colName+"', but the data says it doesn't contain such a column.")
            //break
        }
    }
    var orderedData = [];
    for (var i=0; i<rawData.length; i++) {
        var row = [];
        row[0] = i; // INITIAL_IDX
        for (var j=1; j<colMetadata.length; j++) {
        //alert(""+orderedIdxToRawIdx.get(j)+" to "+j+"")
            row[j] = rawData[i][orderedIdxToRawIdx.get(j)+1];
        }
        orderedData[i] = row;
    }
    return orderedData;
    
}
function _DataTableManager_reorderDataNew(rawData, colMetadata) {
    var orderedData = [];
    //returns null so that the section header is not displayed when theer is no data for the section
    if (rawData.totalSize==0) return null;
    for (var i=0; i<rawData.totalSize; i++) {
        var row = [];
        row[0] = i; // INITIAL_IDX
        for (var j=1; j<colMetadata.length; j++) {
        //alert(""+orderedIdxToRawIdx.get(j)+" to "+j+"")
                var colmnName =colMetadata[j][0];
                var rowNm ='rawData.row[i].'+colmnName.toLowerCase() ;
                if(rawData.totalSize==1){
                        rowNm ='rawData.row.'+colmnName.toLowerCase() ;
                }
                row[j] = eval(rowNm);
        }
        orderedData[i] = row;
    }
    return orderedData;

}

function _DataTableManager_getDataTable(data, colMetadata, initialSortColCode, tableTitle) {
    var dataTable = new DataTable(data, colMetadata, initialSortColCode, tableTitle);
    dataTable.tableManagerIdx = this.dataTables.length;
    this.dataTables[dataTable.tableManagerIdx] = dataTable;
    return dataTable;
}

function _DataTableManager_copyArray(a) {
    if (a == null) {
        return null;
    }
    var ret = [];
    for (var i=0; i<a.length; i++) {
        ret[i] = a[i];
    }
    return ret;
}

// "native" sort functions (others can be added to implementing pages):
function alphaSort(a1, a2) {
    var idx = DataTableManager.currSortColIndex;
    var s1  = (a1[idx]==null?"":""+a1[idx]);
    var s2  = (a2[idx]==null?"":""+a2[idx]);
    if (s1 == s2) {
        return 0;
    }
    var ret = (s1>s2?1:-1);
    return (DataTableManager.currSortAscending?ret:ret*-1);
}

function numericSort(a1, a2) {
    var idx = DataTableManager.currSortColIndex;
    var n1 = a1[idx];
    var n2 = a2[idx];
    var ret; 

    if (n1 == "*.**") { n1 = Number.POSITIVE_INFINITY; }  // handle when ERA passed as something other than a number
    if (n2 == "*.**") { n2 = Number.POSITIVE_INFINITY; } 
    if (n1 == "-")    { n1 = Number.NEGATIVE_INFINITY; }  // handle "empty" stats
    if (n2 == "-")    { n2 = Number.NEGATIVE_INFINITY; } 
    if (n1 == "---")  { n1 = Number.NEGATIVE_INFINITY; } 
    if (n2 == "---")  { n2 = Number.NEGATIVE_INFINITY; } 

    try { 
        var re = /,/g;  // strip commas before trying to parse the number
        n1 = (n1?parseFloat(n1.replace(re,"")):0);
        n2 = (n2?parseFloat(n2.replace(re,"")):0);
    } catch (e) { }

    if (n1 == n2) {
        return 0
    }
    ret = (n1 > n2?1:-1);
    return (DataTableManager.currSortAscending?ret:ret*-1);   // reverse sort order if not ascending
}

var DataTableManager = new _DataTableManager();

// needs to be defined here because some types don't define it:
var dataTable1 = null;

var dataTableManagerLoaded = true;

/////////// END DATATABLEMANAGER OBJECT SCRIPTS ///////////



/////////// START GENERAL SCRIPTS ///////////


// used for filtering of many columns:
function isOverZero(v, rowArr) {
    // note: rowArr is ignored
    if (v == null || v == "") { v = 0; } 
    v = parseFloat(v);
    return (v>0);
}

// actually NOT at-bats minimum but total-plate-appearances minimum:
function meetsAtBatsMinimum(v, rowArr) {
    // ouch: I need to not have the col idx hardcoded: 
    //var totalPlateAppearances=rowArr[25];
    //var gamesPlayed=rowArr[6];

    // if we are in post season or offseason then we show the plate
    // appearances is against the league games, not games played by
    // the team.
    // 
    // ... except if we're looking at playoff stats
	var qualifiesFlag=rowArr[29];
	var qualifies = false;
    try {
        //var seasonState = properties.leagues["l"+lid].season_state;
        //var periodParam = request.getParameter("period");
        //if (((seasonState == "postseason" ) || (seasonState == "offseason" )) && (periodParam != "playoff")) { 
          //  if (rowArr[27]) {
            //    gamesPlayed = rowArr[27];
            //}
        //}
        if (qualifiesFlag == "Y" )  {
                qualifies =  true;
        }
    } catch(e) { }

    return qualifies;
}

// used for filtering of many columns:
function meetsInningsPitchedMinimum(v, rowArr) {
    // ouch: I need to not have the col idx hardcoded:
    //var totalInningsPitched = rowArr[15]; // IP_SORT
    //var teamGamesPlayed = rowArr[4];      // TEAM_GAME
    //return (totalInningsPitched >= reqdInningsPitchedLeagueLeaders * teamGamesPlayed);
    var qualifiesFlag=rowArr[26];
	var qualifies = false;
	if (qualifiesFlag == "Y" )  {
                qualifies =  true;
        }
        return qualifies;
	
}

function getYmdParam(dateObj) {
    if (typeof dateObj=="undefined") {
//        alert("in getYmdParam(), dateObj is undefined.");
    }
    var yr = "" + dateObj.getFullYear();
    var mo = dateObj.getMonth() + 1;
    if (("" + mo).length==1) {
        mo = "0" + mo;
    }
    var dt = dateObj.getDate()
    if (("" + dt).length == 1) {
        dt = "0" + dt;
    }
    return yr + mo + dt;
}

// determine if we're on a branded stats page
function isBrandedPage() {
    try {
        if (location.href.indexOf("external/branded") > -1) { return true; }
        if (parent.location.href.indexOf("external/branded") > -1) { return true; }
    } catch(e) {}

    return false;
}

function writeYearSelect() {

    // if we're on a branded page, dont give the option to show stats from other years 
    if (isBrandedPage()) { return ""; }

    var url;
    var today = new Date();
    var statsStart = 2005;   // year stats start
    var statsData = today.getFullYear();   // year stats start 
    var style;
    if (type=="t_sch") {
	    document.write("<div class=\"statsYearSelect\" style=\"text-align: right; margin-bottom: 4px; font-weight: bold;\">Results for : ");
    }
    else {
	    document.write("<div class=\"statsYearSelect\" style=\"text-align: right; margin-bottom: 4px; font-weight: bold;\">Stats for : ");
    }

    if (request.getParameter("y")) { 
        url = "";
        var params = request.getParameterNames();
        for (var i=0; i<params.length; i++) { 
            if (params[i] != "y") {
                url += "&" + params[i] + "=" + request.getParameter(params[i]);
            }
        }
        var path = document.location.pathname;
        if (!path) { path = "/milb/stats/stats.jsp"; }
        while(statsData >= statsStart) { 
            try { 
                if (year == statsData) { 
                    document.write("<span style=\"font-size: 16px;\">" + statsData + "</span> ");
                } else {
                    document.write("<a href=\"" + path + "?y=" + statsData + url + "\"" + style + ">" + statsData + "</a> ");
                }
            } catch (e) { }
            statsData--;
        }
    } else {
        url = document.location.href;
        while(statsData >= statsStart) { 
            try {
                if (year == statsData) {
                    document.write("<span style=\"font-size: 16px;\">" + statsData + "</span> ");
                } else { 
                    document.write("<a href=\"" + url + "&y=" + statsData + "\" " + style + ">" + statsData + "</a> ");
                }
            } catch (e) { }
            statsData--;
        }
    }
    document.write("</div>");
}

function returnTrue() {
    //function that always returns true
    return true;
}

var typesToSuffixesMap = new HashMap();
typesToSuffixesMap.put("l_bat","playerBatLead"); // league leaders, batting
typesToSuffixesMap.put("l_pit","playerPitLead"); // league leaders, pitching
typesToSuffixesMap.put("l_att","att");
typesToSuffixesMap.put("l_sta","sta");
typesToSuffixesMap.put("l_wcd","wcd");
typesToSuffixesMap.put("l_tra","tra");
typesToSuffixesMap.put("l_sco","sco");
typesToSuffixesMap.put("t_ros","ros");
typesToSuffixesMap.put("t_sch","sch");
typesToSuffixesMap.put("g_box","box");
typesToSuffixesMap.put("g_lin","lin");
typesToSuffixesMap.put("g_log","log");
typesToSuffixesMap.put("g_wra","wra");
typesToSuffixesMap.put("l_tba","teamBat"); // league-level team batting
typesToSuffixesMap.put("l_tpi","teamPit"); // league-level team pitching
typesToSuffixesMap.put("t_tst","teamLeagueRec"); // team stats

typesToSuffixesMap.put("t_alu",null); // alumni report: unlike other resultsets, handled as a special case since two files may have to be imported
typesToSuffixesMap.put("t_ibp",null); // individual batting, pitching: unlike other resultsets, handled as a special case since two files may have to be imported
typesToSuffixesMap.put("p_pbp",null); // player batting, pitching: unlike other resultsets, handled as a special case since two files may have to be imported
typesToSuffixesMap.put("p_top",null); // top prospect profile: handled as a special case since multiple files imported

var entityId = "";
var statsTier = "";
var altDefaultSortCol  = request.getParameter("adsc");
// for when we potentially have two different table types on a page (e.g. batting and pitching):
var altDefaultSortCol2 = request.getParameter("adsc2");
var clubId   = request.getParameter("cid");
var leagueId = request.getParameter("lid");
var gameId   = request.getParameter("gid");
var playerId = request.getParameter("pid");
var type     = request.getParameter("t");
var year     = request.getParameter("y");

if (year == null) {
    year = season_year;
}
var statsTierShort = "";

if (clubId == null) {
    clubId = "milb";
}

if (type == null) {
    if (!(window["isLinescorePage"])) {
        // alert("Error: t param (type) not specified.");
        // window.status = "Error: t param (type) not specified.";
    } else {
        type = "t_lin";
    }
}

if (type.indexOf("l_") == 0) {
    statsTier = "leagues";
    statsTierShort = "l";
//    if (leagueId==null) alert("Error: lid param (league ID) not specified.");
    entityId = leagueId;
} else if (type.indexOf("g_") == 0) {
    statsTier = "games";
    statsTierShort = "g";
//    if (gameId==null) alert("Error: gid param (game ID) not specified.");
    entityId = gameId;
} else if (type.indexOf("p_") == 0) {
    statsTier = "players";
    statsTierShort = "p";
//    if (playerId==null) alert("Error: pid param (player ID) not specified.");
    entityId = playerId;
} else if (type.indexOf("t_") == 0) {
    statsTier = "clubs";
    statsTierShort = "t";
    entityId = clubId;
}

var filenameSuffix = typesToSuffixesMap.get(type);
var ymdParam = null;

// this if/else is out of control ... 

// Get the data:
if (!(window["isLinescorePage"])) {
	if (filenameSuffix!=null) {
		// if filename suffix isn't null, then we just import the data 
		// (with the exception of wraps and scoreboards; these special cases 
		// is handled in this clause too), which will be in the form of an array called "raw":
		if (!(type == "g_wra")) {
			if (type == "l_sco") {
				// need support for the date selector
				ScriptIncluder.include("/scripts/date_selector.js", false);
				
				// special case: need to import a date-specific scoreboard datafile:

				var seasonState = properties.leagues["l"+lid].season_state;
				var lastGame = properties.leagues["l"+lid].last_game;

				ymdParam = request.getParameter("ymd");
				if (ymdParam == null) {
					if (seasonState == "offseason") {
						ymdParam = lastGame.substring(0,4) + lastGame.substring(5,7) + lastGame.substring(8,10);
					}
					else {
						ymdParam = getYmdParam(getNowDate(-10));
					}
				}
				var leaguePath    = leagueId;
				var leagueNumPath = leagueId;
				if (leaguePath.charAt(0) != "l") { leaguePath = "l" + leaguePath; }
				if (leagueNumPath.charAt(0) == "l") { leagueNumPath = leagueNumPath.substring(1); }
				
				//var dataUrl ="/gen/stats/jsdata/" + year + "/leagues/" + leagueId + "_" + ymdParam + "_sco.js";
				var dataUrl ="/gen/stats/jsdata/games/scoreboard/" + year + "/" + leaguePath + "/" + ymdParam + "_league_" + leagueNumPath + ".js";

			} else if (type == "l_tra") {
				// special case: need to import a month-specific transactions datafile
				ymdParam=request.getParameter("ymd");
				if (ymdParam==null) {
					ymdParam=getYmdParam(getNowDate()).substring(0,6);
				}
				var transactionsYear = ymdParam.substring(0,4); // we need to look not in the 'current' stats year, but the year for the actual transaction occurance

				var dataUrl ="/gen/stats/jsdata/" + transactionsYear + "/leagues/l" + leagueId + "_" + ymdParam + "_tra.js";

			} else if (type == "l_sta") {
				// special case: we need to look at if we're showing current, or 1st half standings
				// this is passed by the 'period' param, which is set to h1 when looking for first half standings
				var leaguePath = leagueId;
					if (leaguePath.charAt(0) != "l") leaguePath = "l" + leaguePath;
				periodParam = request.getParameter("period");
				switch(periodParam) {
					case "h1": 
						var dataUrl ="/gen/stats/jsdata/leagues/" + year + "/" + leaguePath + "/standings_h1.js";
						break;
					case "h2":
						var dataUrl ="/gen/stats/jsdata/leagues/" + year + "/" + leaguePath + "/standings_h2.js";
						break;
					case "wildcard":
						var dataUrl ="/gen/stats/jsdata/leagues/" + year + "/" + leaguePath + "/standings_wildcard.js";
						break;
				//	case "h1_wildcard": 
				//		var dataUrl ="/gen/stats/jsdata/leagues/" + year + "/" + leaguePath + "/standings_h1_wildcard.js";
				//		break;
				//	case "h2_wildcard":
				//		var dataUrl ="/gen/stats/jsdata/leagues/" + year + "/" + leaguePath + "/standings_h2_wildcard.js";
				//		break;
					default: 
						var dataUrl ="/gen/stats/jsdata/leagues/" + year + "/" + leaguePath + "/standings.js";
						break;
				}

			} else if (type == "l_wcd") {
				var leaguePath = leagueId;
					if (leaguePath.charAt(0) != "l") leaguePath = "l" + leaguePath;
				periodParam = request.getParameter("period");
				switch(periodParam) {
					case "h1_wildcard": 
						var dataUrl ="/gen/stats/jsdata/leagues/" + year + "/" + leaguePath + "/standings_h1_wildcard.js";
						break;
					case "h2_wildcard":
						var dataUrl ="/gen/stats/jsdata/leagues/" + year + "/" + leaguePath + "/standings_h2_wildcard.js";
						break;
					case "wildcard":
						var dataUrl ="/gen/stats/jsdata/leagues/" + year + "/" + leaguePath + "/standings_wildcard.js";
						break;
				}


			} else if (type == "l_att") {
				var leaguePath = leagueId;
				if (leaguePath.charAt(0) != "l") leaguePath = "l" + leaguePath;
				var dataUrl ="/gen/stats/jsdata/leagues/" + leaguePath + "_att.js";

			} else if (type == "g_log") { // this if/else thing here is a big, huge, mess
				var pathYear  = gameId.substring(0,4);
				var pathMonth = gameId.substring(5,7);
				var pathDay   = gameId.substring(8,10);
				var gameIdForPath = gameId.replace(/\//g,"_").replace(/-/g,"_");
				var dataUrl ="/gen/stats/jsdata/games/year_" + pathYear + "/month_" + pathMonth + "/day_" + pathDay + "/gid_"+request.getParameter("gid")+"/log.js";

			} else if (type == "g_box") { // this if/else thing here is a big, huge, mess
				var pathYear  = gameId.substring(0,4);
				var pathMonth = gameId.substring(5,7);
				var pathDay   = gameId.substring(8,10);
				var gameIdForPath = gameId.replace(/\//g,"_").replace(/-/g,"_");
				var dataUrl ="/gen/stats/jsdata/games/year_" + pathYear + "/month_" + pathMonth + "/day_" + pathDay + "/gid_"+request.getParameter("gid")+"/box.js";

			} else if (type=="t_ros"){ // this if/else thing here is a big, huge, mess
				var dataUrl="/gen/stats/jsdata/"+statsTier+"/"+statsTierShort+""+entityId+"_"+filenameSuffix+".js";
			} else if (type=="t_sch") { // this if/else thing here is a big, huge, mess
				var dataUrl="/gen/stats/jsdata/"+year+"/"+statsTier+"/"+statsTierShort+""+entityId+"_"+filenameSuffix+".js";

			} else {
				// special case: we need to look at if we're showing current, or just post season stats
				//
				// this is passed by the 'period' param, which is
				// set to 'playoff' for post season batting/pitching playoff stats
				periodParam = request.getParameter("period");
				if (periodParam == "playoff") {
					var dataUrl ="/gen/stats/jsdata/"+year+"/"+statsTier+"/"+statsTierShort+""+entityId+"_"+filenameSuffix+"Playoff.js";
				} else {
					var dataUrl ="/gen/stats/jsdata/"+year+"/"+statsTier+"/"+statsTierShort+""+entityId+"_"+filenameSuffix+".js";
				}
			}

			ScriptIncluder.include(dataUrl, true);

		} else { // else t=g_wra
			var pathYear  = gameId.substring(0,4);
			var pathMonth = gameId.substring(5,7);
			var pathDay = gameId.substring(8,10);
			var gameIdForPath = gameId.replace(/\//g,"_").replace(/-/g,"_");

			// put this in later, once generation is changed and files migrated by CMS
			// var dataUrl="/gen/stats/jsdata/games/year_" + pathYear + "/month_" + pathMonth + "/day_" + pathDay + "/gid_"+request.getParameter("gid")+"/wrap.js";
			var dataUrl="/gen/stats/jsdata/games/"+gameIdForPath+"/wrap.js";
			ScriptIncluder.include(dataUrl, true);
		}

	} else { // else filenameSuffix == null, which means we have to handle the importing of data as a
				// special case, because two datasets (batting, pitching) need to be imported:
		if (type == "t_alu") {
			// alumni report:
			var dataUrl1 ="/gen/stats/jsdata/" + year + "/" + statsTier + "/" + statsTierShort + "" + entityId + "_playerBatAlum.js";
			var dataUrl2 ="/gen/stats/jsdata/" + year + "/" + statsTier + "/" + statsTierShort + "" + entityId + "_playerPitAlum.js";
			ScriptIncluder.include(dataUrl1, true);
			ScriptIncluder.include(dataUrl2, true);
		
		} else if (type == "t_ibp") {
			// indiv batting/pitching:
			var dataUrl1 ="/gen/stats/jsdata/" + year + "/" + statsTier + "/" + statsTierShort + "" + entityId + "_playerBat.js";
			var dataUrl2 ="/gen/stats/jsdata/" + year + "/" + statsTier + "/" + statsTierShort + "" + entityId + "_playerPit.js";
			ScriptIncluder.include(dataUrl1, true);
			ScriptIncluder.include(dataUrl2, true);
		
		} else if (type == "p_top") {
			// top prospect profile: stats, bio, awards
			
		} else if (type == "p_pbp") {
			
			//var dataUrl9   ="/gen/stats/jsdata/" + statsTier + "/" + statsTierShort + entityId + "/" + statsTierShort + entityId + "Bio.js";
			var dataUrl10  = "/gen/stats/jsdata/" + statsTier + "/" + statsTierShort + entityId + "/" + statsTierShort + entityId + "biographyinfo.jsp?hashName=biographyInfo";


			var dataUrl11 = "/gen/stats/jsdata/" + statsTier + "/" + statsTierShort + entityId + "/" + statsTierShort + entityId + "YearHighlights.js";

			if (dataUrl10) { ScriptIncluder.include(dataUrl10, true); }
			if (dataUrl11) { ScriptIncluder.include(dataUrl11, true); }
		}

	} // end else: filenamesuffix == null

} else { // else t=g_lin
	var pathYear  = gameId.substring(0,4);
	var pathMonth = gameId.substring(5,7);
	var pathDay   = gameId.substring(8,10);
	var gameIdForPath = gameId.replace(/\//g,"_").replace(/-/g,"_");

	var dataUrl ="/gen/stats/jsdata/games/year_" + pathYear + "/month_" + pathMonth + "/day_" + pathDay + "/gid_"+request.getParameter("gid")+"/lin.js";
	ScriptIncluder.include(dataUrl, true);
}

// Get the scripts to write the data for this type of resultset:
if (!(window["isLinescorePage"])) {
	ScriptIncluder.include("/stats/js/datawriters/" + type + ".jsp?sid=" + sid + "&lid=" + lid, false);
} else {
	// Get the scripts to write the data for this type of resultset:
	var filename = "";
	if (typeof isGameStatusLinescore == "undefined") {
		isGameStatusLinescore = false;
	}
	if (isGameStatusLinescore) {
		filename = "g_lsg.jsp?sid=" + sid + "&home=t" + homeClubID + "&away=t" + visitingClubID;
	} else {
		filename = "g_lin.jsp?sid=" + sid + "&home=" + request.getParameter("home") + "&away=" + request.getParameter("away");
	}
	ScriptIncluder.include("/stats/js/datawriters/" + filename, true);
}

/////////// END GENERAL SCRIPTS ///////////



