﻿// Temporal heat index - Grid control

function GRID() { };

GRID.Init = function() {
    //alert("GRID.Init");

    GRID.HaveLiterals = false;
    GRID.LayerID = "";
    GRID.Content = "count";
    GRID.RefreshRecordSet = false;
};

GRID.DefineLiterals = function(data, status) {
    //alert("GRID.DefineLiterals, status = " + status);

    GRID.CannotUpdateMap = data.CannotUpdateMap;
    GRID.ClickCell = data.ClickCell;
    GRID.Selected = data.Selected;
    GRID.AverageDesc = data.AverageDesc;
    GRID.TotalDesc = data.TotalDesc;
    GRID.AllDaysDesc = data.AllDaysDesc;
    GRID.AllTimesDesc = data.AllTimesDesc;
    GRID.MinDesc = data.MinDesc;
    GRID.MaxDesc = data.MaxDesc;
    GRID.AvgDesc = data.AvgDesc;
    GRID.TotDesc = data.TotDesc;
    GRID.StdDevDesc = data.StdDevDesc;
    GRID.StandardDeviationsDesc = data.StandardDeviationsDesc;
    GRID.DOWWarning = data.DOWWarning;
    GRID.Days = data.Days;

    GRID.HaveLiterals = true;
    GRID.CellFontColor = "#000";
    GRID.CellTotalColor = "#fff";
    GRID.CellColors = new Array("#001CC4", "#0059FF", "#6299FF", "#93BCFF", "#C1E0FF", "#E8F3FF", "#FFFF80", "#FFC040", "#FF8000", "#FF4000", "#C00000");

    GRID.SendDataRequest();
};

GRID.Reset = function() {
    //alert("GRID.Reset");

    GRID.SummaryData = null;
    GRID.LayerName = "Items";
    GRID.LayerQuery = "";
    GRID.WhenQuery = "";
    GRID.StdDev = 0.0;
    GRID.Breaks = new Array();
    GRID.NumBreaks = 10;
    GRID.HaveSubset = false;
    GRID.RefreshRecordSet = false;
    GRID.CellList = [];

    //$("#grid-header").hide();
    //$("#grid-content").hide();
    //$("#grid-fields").hide();
    $("#grid-subset-content").hide();
    //$("#grid-data").html("");
};

GRID.GetGridData = function(lyrID) {
    //alert("GRID.GetChartData");
    GRID.LayerID = lyrID;
    GRID.Reset();

    if (GRID.HaveLiterals) {
        GRID.SendDataRequest();
    } else {
        $.ajax(
    	{
    	    type: "GET",
    	    url: "Data.aspx",
    	    data: "page=gridliterals",
    	    dataType: "json",
    	    error: UIHelper.AjaxError,
    	    success: GRID.DefineLiterals
    	});
    }
};
GRID.SendDataRequest = function() {
    var d = new Date();
    $.ajax(
  	    {
  	        type: "GET",
  	        url: "data.aspx",
  	        data: "page=grid&id=" + GRID.LayerID + "&how=" + GRID.Content + "&t=" + d.getTime(),
  	        dataType: "json",
  	        error: GRID.AjaxError,
  	        success: GRID.ProcessGridData
  	    });
};
GRID.AjaxError = function(XMLHttpRequest, status) {
    alert("GRID.AjaxError = " + XMLHttpRequest.toString + ", " + status);
};

GRID.ProcessGridData = function(data, status) {
//alert("GRID.ProcessGridData = " + data.total);
if (data.total == 0) {
        $("#grid-header").html(data.message);
        $("#grid-content").hide();
        $("#grid-fields").hide();
        $("#grid-update-button").hide();
        //$("#grid-header").show();
        CVS.StopProgressBar();
        return;
    }
    // Save the data locally
    GRID.LayerName = data.name;
    GRID.CalcAverage = (data.style == "average");
    GRID.Format = data.format;
    GRID.TotalCells = data.cells;
    GRID.TotalRecs = data.total;
    GRID.Average = data.average;
    GRID.Minimum = data.minimum;
    GRID.Maximum = data.maximum;
    GRID.SummaryData = data.summary;
    if (GRID.CalcAverage) {
        GRID.AvgTotDesc = GRID.AvgDesc;
        GRID.AverageTotalDesc = GRID.AverageDesc;
    } else {
        GRID.Minimum = 0.001; // Keeps count style cells with value 0 from being clickable
        GRID.AvgTotDesc = GRID.TotDesc;
        GRID.AverageTotalDesc = GRID.TotalDesc;
    }

    if (UIHelper.IsLinkMap) {
        $("#grid-header").html("");
        //$("#grid-fields").hide();
    } else {
        $("#grid-header").html("<p>" + GRID.ClickCell + "<br/>" + GRID.LayerName + ": " + GRID.TotalDesc + " = " + GRID.TotalRecs + "</p>");

        var fields = data.how.fields;
        if (fields.length > 0) {
            var s = '<select id="lstGridFields" onchange="GRID.GridFieldChanged();">';
            s += '<option value="count">Count</option>';
            for (var idx = 0; idx < fields.length; idx++) {
                s += '<option value="' + fields[idx].val + '"';
                if (fields[idx].val == GRID.Content) s += ' selected="selected"';
                s += '>' + fields[idx].desc + '</option>';
            }
            s += '</select>';
            $("#grid-fields-list").html(s);
            $("#grid-fields").show();
        } else {
            //$("#grid-fields").hide();
        }
    }
    //$("#grid-header").show();

    GRID.HaveSubset = false;
    GRID.CellList.length = 0;
    $("#grid-update-button").hide();

    GRID.BuildGrid();

    // Needed when undoing a drilldown
    GRID.LayerQuery = WHAT.GetLayerQuery(GRID.LayerID);
    //alert("GRID.LayerQuery = " + GRID.LayerQuery);

    // Allow another postback request
    CVS.StopProgressBar();

    $("#grid-content").slideDown();

    if (data.badrecs > 0) UIHelper.ShowStatusMessage(GRID.DOWWarning + " " + data.badrecs, "warning");
};

GRID.GridFieldChanged = function() {
    GRID.Content = $("#lstGridFields :selected").val();

    if (GRID.HaveSubset) {
        GRID.UpdateMapForAllGridCells();
    } else {
        $("#grid-subset-content").hide();

        GRID.SendDataRequest();
    }
};

GRID.BuildGrid = function() {
    var rx, cx, cols, val = 0, vf;
    var d, s, hour, cell, style;
    var pre = "0", id;

    GRID.CellList.length = 0;

    GRID.CalcStdDev();

    d = "<table id='grid-table' cellpadding='0' cellspacing='0'>"
      + "<tr>"
      + "<td class='dow'>&nbsp;</td>";
    for (cx = 0; cx < 7; cx++) {
        d += "<td class='dow'>" + GRID.Days[cx] + "</td>";
    }
    d += "<td class='dow'>" + GRID.AvgTotDesc + "</td>";
    d += "</tr>";

    for (rx = 0; rx < 24; rx++) {
        if (rx > 9) pre = "";
        hour = pre + rx;
        s = "<tr><td class='hour'>" + hour + "</td>";
        cols = GRID.SummaryData[rx].col;
        for (cx = 0; cx < 8; cx++) {
            val = cols[cx].val;
            if (val < GRID.Minimum || UIHelper.IsLinkMap) {
                //onclick = "";
                if (cx == 7) {
                    cell = "hour-total";
                    style = "background-color:" + GRID.CellTotalColor + ";";
                } else {
                    cell = "cell";
                    style = "background-color:" + GRID.GetColor(val) + ";";
                }
            } else {
                if (cx == 7) {
                    cell = "hour-total-data";
                    style = "background-color:" + GRID.CellTotalColor + ";";
                } else {
                    cell = "cell-data";
                    style = "background-color:" + GRID.GetColor(val) + ";";
                    style += "color:" + GRID.CellFontColor+";"
                }
                style += "cursor:pointer;";
            }
            vf = val.toFixed(3).replace(".", "_");
            id = rx + "-" + cx + "-" + vf;
            s += "<td id='" + id + "' class='" + cell + "' style='" + style + "'>" + GRID.FormatCell(val) + "</td>";
        }
        s += "</tr>";
        d += s;
    }
    s = "<tr><td class='hour'>" + GRID.AvgTotDesc + "</td>";
    cols = GRID.SummaryData[24].col;
    for (cx = 0; cx < 8; cx++) {
        val = cols[cx].val;
        style = "background-color:" + GRID.CellTotalColor + ";";
        if (val < GRID.Minimum || UIHelper.IsLinkMap) {
            //onclick = "";
            cell = "cell-bottom";
        } else {
            cell = "cell-bottom-data";
            style += "cursor:pointer;";
        }
        vf = val.toFixed(3).replace(".", "_");
        id = "24-" + cx + "-" + vf;
        s += "<td id='" + id + "' class='" + cell + "' style='" + style + "'>" + GRID.FormatCell(val) + "</td>";
    }
    s += "</tr></table>";
    d += s;

    $("#grid-data").html(d);

    $("#grid-table td").click(function(e) {
        var vals = this.id.split("-")
        var t = parseFloat(vals[2].replace("_", "."));
        if (t < GRID.Minimum) return;

        if (e.shiftKey) {
            alert("To select multiple cells, press the control key when clicking a cell.")
            return;
        }
        if (e.ctrlKey) {
            //alert("control+click = " + this.id)
            GRID.UpdateCellList(this.id);
        } else {
            var r = parseInt(vals[0]);
            var c = parseInt(vals[1]);
            GRID.CellClick(r, c, t);
        }
    });
};

GRID.UpdateCellList = function(id) {
    $("#grid-update-button a").focus();
    for (idx = 0; idx < GRID.CellList.length; idx++) {
        if (GRID.CellList[idx] == id) {
            GRID.CellList.splice(idx, 1);
            $("#" + id).css("border", "");
            if (GRID.CellList.length == 0) $("#grid-update-button").hide();
            return;
        }
    }
    GRID.CellList.push(id);
    //alert("id = " + id + ", = " + $("#" + id));
    $("#" + id).css("border", "2px solid black");
    $("#grid-update-button").show();
};

GRID.GetColor = function(val) {
    if (GRID.CalcAverage && val < GRID.Minimum) return GRID.CellTotalColor;

    var chkVal = (val - GRID.Average) / GRID.StdDev;

    var bgIdx = GRID.NumBreaks;
    for (var idx = 0; idx < GRID.NumBreaks; idx++) {
        if (GRID.Breaks[idx] >= chkVal) {
            bgIdx = idx;
            break;
        }
    }

    if (bgIdx < 3 || bgIdx > 7) { GRID.CellFontColor = "#fff"; } else { GRID.CellFontColor = "#000"; }
    
    return GRID.CellColors[bgIdx];
};

GRID.FormatCell = function(val) {
    if (GRID.CalcAverage && val < GRID.Minimum) return "&nbsp;";

    var s;
    if (GRID.Format == "time") {
        var n1 = Math.floor(val);
        var n2 = val - parseFloat(n1);
        var n3 = parseInt(60 * n2);
        //alert("val = " + val + ", n1 = " + n1 + ", n2 = " + n2 + ", n3 = " + n3 + ", < 10 = " + (n3 < 10));
        if (n3 < 10) {
            s = n1 + ":0" + n3.toString();
        } else {
            s = n1 + ":" + n3.toString();
        }
    } else {
        var dp = parseInt(GRID.Format);
        s = val.toFixed(dp);
    }

    return s;
};

GRID.CellClick = function(row, col, count) {
    //alert("Row = " + row + ", Col = " + col);

    if (GRID.CellList.length > 0) GRID.ClearSelectedCells();

    if (row == 24 && col == 7) {
        GRID.UpdateMapForAllGridCells();
        return;
    }

    var dates = "";
    var idx, hour = "", time = "", dow = "", dayDesc = "", timeDesc = "";

    if (col < 7) {
        for (idx = 0; idx < col; idx++) dow += "0";
        dow += "1";
        for (idx = col + 1; idx < 7; idx++) dow += "0";
        dayDesc = GRID.Days[col];
    } else {
        dayDesc = GRID.AllDaysDesc;
    }

    if (row < 24) {
        if (row < 10) hour = "0";
        hour += row;
        time = hour + "00" + hour + "59";
        timeDesc = hour;
    } else {
        timeDesc = GRID.AllTimesDesc;
    }

    if (WHEN.IsValid) dates = WHEN.DateSelection;

    GRID.WhenQuery = dates + "|" + time + "|Sliced|" + dow;

    //alert("GRID.WhenQuery = " + GRID.WhenQuery);

    if (GRID.LayerQuery == "") {
        UIHelper.ShowStatusMessage(GRID.CannotUpdateMap, "warning");
    } else {
    GRID.HaveSubset = true;
    UIHelper.UpdateGridDrilldownMap();
        $("#report-tab a").unbind("click");
        $("#report-tab a").bind("click", function(e) { UIHelper.SetupReportTab(); });
        $("#grid-subset").html("<p>" + GRID.Selected + ": " + dayDesc + "-" + timeDesc + ", " + GRID.AverageTotalDesc + " = " + GRID.FormatCell(count) + "</p>");
        $("#grid-subset-content").show();
    }
};

GRID.ClearSelectedCells = function() {
    for (var idx = 0; idx < GRID.CellList.length; idx++) {
        $("#" + GRID.CellList[idx]).css("border", "");
    }

    $("#grid-update-button").hide();
    
    GRID.CellList.length = 0;
};

GRID.UpdateMap = function() {
    //alert("GRID.UpdateMap = " + GRID.CellList.length);
    var vals, row, col, tot = 0.0, rowTot = 0, colTot = 0, cellTot = 0;
    var idx, gIdx, hour, time, dow;
    var dates = "", bar = "", when = "";
    var rowDesc = "", colDesc = "", cellDesc = "";

    if (WHEN.IsValid) dates = WHEN.DateSelection;

    for (gIdx = 0; gIdx < GRID.CellList.length; gIdx++) {
        vals = GRID.CellList[gIdx].split("-")
        row = parseInt(vals[0]);
        col = parseInt(vals[1]);
        tot += parseFloat(vals[2].replace("_", "."));

        dow = "";
        if (col < 7) {
            for (idx = 0; idx < col; idx++) dow += "0";
            dow += "1";
            for (idx = col + 1; idx < 7; idx++) dow += "0";
        } else {
            dow = "1111111";
            rowTot++;
        }

        if (row < 24) {
            if (row < 10) { hour = "0"; } else { hour = ""; }
            hour += row;
            time = hour + "00" + hour + "59";
        } else {
            time = "00002359";
            colTot++;
        }
        if (col < 7 && row < 24) cellTot++;

        when += bar + dates + "|" + time + "|Sliced|" + dow;
        bar = "|";
    }
    if (GRID.CalcAverage) tot /= parseFloat(GRID.CellList.length);

    GRID.WhenQuery = when;

    if (GRID.LayerQuery == "") {
        UIHelper.ShowStatusMessage(GRID.CannotUpdateMap, "warning");
    } else {
    GRID.HaveSubset = true;
    UIHelper.UpdateGridDrilldownMap();

        if (cellTot > 0) {
            cellDesc = cellTot + " cell";
            if (cellTot > 1) cellDesc += "s";
        }
        if (rowTot > 0) {
            if (cellTot > 0) rowDesc = ", ";
            rowDesc += rowTot + " row";
            if (rowTot > 1) rowDesc += "s";
        }
        if (colTot > 0) {
            if (cellTot > 0 || rowTot > 0) colDesc = ", ";
            colDesc += colTot + " column";
            if (colTot > 1) colDesc += "s";
        }

        $("#report-tab a").unbind("click");
        $("#report-tab a").bind("click", function(e) { UIHelper.SetupReportTab(); });
        if (rowTot > 0 || colTot > 0) {
            $("#grid-subset").html("<p>" + GRID.Selected + ": " + cellDesc + rowDesc + colDesc + "</p>");
        } else {
        $("#grid-subset").html("<p>" + GRID.Selected + ": " + cellDesc + ", " + GRID.AverageTotalDesc + " = " + GRID.FormatCell(tot) + "</p>");
        }
        $("#grid-subset-content").show();
    }
};

GRID.CalcStdDev = function() {
    var rx, cx, cols, val, sqrAvg, sqrTot = 0.0, stdDev;

    // Calc the total value of the sqrt of all cells
    for (rx = 0; rx < 24; rx++) {
        cols = GRID.SummaryData[rx].col;
        for (cx = 0; cx < 7; cx++) {
            // Skip cells that are less than the minimum when displaying cell average rather than cell total
            if (GRID.CalcAverage && cols[cx].val < GRID.Minimum) continue;
            
            val = cols[cx].val - GRID.Average;
            sqrTot += val * val;
        }
    }
    // The std dev is the sqrt of the average of the total sqrts
    sqrAvg = sqrTot / GRID.TotalCells;
    GRID.StdDev = Math.sqrt(sqrAvg);

    //alert("avg = " + GRID.Average + ", sqrt avg = " + sqrAvg + ", std dev = " + GRID.StdDev);

    GRID.NumBreaks = 10;
    GRID.Breaks[0] = -3.0;
    GRID.Breaks[1] = -2.0;
    GRID.Breaks[2] = -1.5;
    GRID.Breaks[3] = -1.0;
    GRID.Breaks[4] = -0.5;
    GRID.Breaks[5] = 0.5;
    GRID.Breaks[6] = 1.0;
    GRID.Breaks[7] = 1.5;
    GRID.Breaks[8] = 2.0;
    GRID.Breaks[9] = 3.0;

    var stats = "<p>"
              + GRID.MinDesc + "&nbsp;=&nbsp;" + GRID.Minimum.toFixed(2) + ", "
              + GRID.MaxDesc + "&nbsp;=&nbsp;" + GRID.Maximum.toFixed(2) + ", "
              + GRID.AvgDesc + "&nbsp;=&nbsp;" + GRID.Average.toFixed(2) + ", "
              + GRID.StdDevDesc + "&nbsp;=&nbsp;" + GRID.StdDev.toFixed(2)
              + "</p>";
    var leg = "<table cellpadding='0' cellspacing='5'><tr>";
    for (cx = 0; cx <= GRID.NumBreaks; cx++) {
        leg += "<td style='background-color:" + GRID.CellColors[cx] + ";'>&nbsp;</td>";
    }
    leg += "</tr><tr>";
    for (cx = 0; cx < GRID.NumBreaks; cx++) {
        switch (cx) {
            case 0:
                leg += "<td>&lt;&nbsp;" + GRID.Breaks[cx].toFixed(1) + "</td>";
                break;
            case 1: case 2: case 3: case 4:
                leg += "<td>" + GRID.Breaks[cx].toFixed(1) + "&nbsp;to<br/>" + GRID.Breaks[cx - 1].toFixed(1) + "</td>";
                break;
            case 5:
                leg += "<td>" + GRID.Breaks[cx - 1].toFixed(1) + "&nbsp;to<br/>+" + GRID.Breaks[cx].toFixed(1) + "</td>";
                break;
            case 6: case 7: case 8: case 9:
                leg += "<td>+" + GRID.Breaks[cx - 1].toFixed(1) + "&nbsp;to<br/>+" + GRID.Breaks[cx].toFixed(1) + "</td>";
                break;
        }
    }
    leg += "<td>&gt;&nbsp;+" + GRID.Breaks[GRID.NumBreaks - 1].toFixed(1) + "</td>";
    leg += "</tr></table>";

    $("#grid-stats").html(stats + leg + "<p>" + GRID.StandardDeviationsDesc + "</p>");
};

GRID.UpdateMapForAllGridCells = function() {
    //alert("GRID.UpdateMapForAllGridCells");
    if (GRID.LayerQuery == "") return;

    GRID.ClearSelectedCells();

    if (GRID.HaveSubset) GRID.RefreshRecordSet = true;

    GRID.HaveSubset = false;
    GRID.WhenQuery = UIHelper.WhenQuery;
    UIHelper.UpdateGridDrilldownMap();

    $("#report-tab a").unbind("click");
    $("#report-tab a").bind("click", function(e) { UIHelper.SetupReportTab(); });

    $("#grid-subset-content").hide();
};

