var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
/************************************************
Blank Space Gadget
************************************************/
var Dashboards;
(function (Dashboards) {
    var Models;
    (function (Models) {
        var HeatMap = (function (_super) {
            __extends(HeatMap, _super);
            function HeatMap(gadgetOptions) {
                gadgetOptions.renderer = new Dashboards.Views.HeatMapRender();
                _super.call(this, gadgetOptions);
            }
            HeatMap.CreateInstance = function (gadgetOptions) {
                var instance = new HeatMap(gadgetOptions);
                return instance;
            };
            HeatMap.prototype.canExportData = function () {
                return false;
            };
            //Overriden function of base class so as to normalize heat map data points.        
            HeatMap.prototype.formatData = function (data) {
                var heatMapDataPoints = null;
                if (data && data.hasOwnProperty('ChartingData') && data.ChartingData && data.ChartingData.DataPoints) {
                    // Convert data format for standard Charting Data
                    heatMapDataPoints = data.ChartingData.DataPoints;
                }
                //Let the chart data gadget base class execute first
                _super.prototype.formatData.call(this, data);
                //Now let us normalize the pareto data point.
                if (!_.isNull(heatMapDataPoints)) {
                    data.ChartingData.DataPoints = this.normalizeChartingDataSeriesHeatMapData(heatMapDataPoints);
                    //set the max and min to calculate the colors during rendering
                    //First filter out any null data points.
                    var dataPoints = _.filter(heatMapDataPoints, function (point) { return !(_.isNull(point.Value) || _.isNaN(point.Value)); });
                    data.ChartingData.Max = _.max(dataPoints, function (point) { return point.Value; });
                    data.ChartingData.Min = _.min(dataPoints, function (point) { return point.Value; });
                }
                return data;
            };
            //This function taken as is from Models.ChartingDataGadget and modified to add 
            //cumulative percentage to normalized data point.
            HeatMap.prototype.normalizeChartingDataSeriesHeatMapData = function (dataPoints) {
                var newDataPoints = {};
                var clearLastLogAfterGap = this.getHandler().byName(Settings.Gadget.ClearLastLogAfterGap.name);
                var removeOutliers = this.getHandler().byName(Settings.Gadget.RemoveOutliers.name).toLowerCase();
                var thresholdMax = Number(this.getHandler().byName(Settings.Gadget.ThresholdMax.name));
                var thresholdMin = Number(this.getHandler().byName(Settings.Gadget.ThresholdMin.name));
                for (var i = 0; i < dataPoints.length; i++) {
                    var origDataPoint = dataPoints[i];
                    if (!newDataPoints[origDataPoint.SeriesName]) {
                        // Create array for series data values
                        newDataPoints[origDataPoint.SeriesName] = [];
                    }
                    //If user wishes to clear the last log after a data gap then do it here.
                    if ('true' === clearLastLogAfterGap && i > 0) {
                        var dt = Date.ParseJsonDate(dataPoints[i - 1].TimestampLocal);
                        if (dt.getFullYear() == 9999) {
                            origDataPoint.Value = null;
                        }
                    }
                    //Time to remove the outliers on both side of the median.
                    if (removeOutliers === 'true' && !(_.isNull(origDataPoint.Value) || _.isUndefined(origDataPoint.Value))) {
                        if (!(origDataPoint.Value > thresholdMin && origDataPoint.Value < thresholdMax)) {
                            origDataPoint.Value = null; //Remove the outlier in case it is more then user defined threshold.
                        }
                    }
                    var dataPoint = [];
                    dataPoint[Models.ChartingDataGadget.AxisLabelIdx] = origDataPoint.SeriesName;
                    dataPoint[Models.ChartingDataGadget.ValueIdx] = origDataPoint.Value;
                    dataPoint[Models.ChartingDataGadget.TimeIdx] = Date.ParseJsonDate(origDataPoint.TimestampLocal);
                    dataPoint[HeatMap.ColorIdx] = origDataPoint.Color; //Add the cumulative percentage to list.                
                    dataPoint[HeatMap.PointLabelIdx] = origDataPoint.TimeLabel; //Add the cumulative percentage to list.                
                    newDataPoints[origDataPoint.SeriesName].push(dataPoint);
                }
                return newDataPoints;
            };
            HeatMap.TypeId = "da06b3a4-6bfa-4085-b01b-0ff6cdc8bcab";
            HeatMap.ColorIdx = Models.ChartingDataGadget.TimeIdx + 1;
            HeatMap.PointLabelIdx = HeatMap.ColorIdx + 1;
            return HeatMap;
        }(Models.ChartingDataGadget));
        Models.HeatMap = HeatMap;
    })(Models = Dashboards.Models || (Dashboards.Models = {}));
})(Dashboards || (Dashboards = {}));
var Dashboards;
(function (Dashboards) {
    var Views;
    (function (Views) {
        var HeatMapRender = (function (_super) {
            __extends(HeatMapRender, _super);
            function HeatMapRender() {
                _super.call(this);
                this.chartVersion = 1; //Current Version of Heat Map
            }
            HeatMapRender.prototype.destroy = function () {
                _super.prototype.destroy.call(this);
                this.clearBarchart();
                this.gadget = null;
            };
            /* Gadget Render Implementation
            **************************************************************************/
            HeatMapRender.prototype.updateGadget = function (handler) {
                var callBack = new Core.CallBack(this.renderContent, this);
                TemplateUtil.LocAndLoad(HeatMapRender.RenderTemplateUri, callBack);
            };
            /* Private Methods
            ******************************************************************************/
            HeatMapRender.prototype.renderContent = function (template) {
                if (!this.$gadgetRender)
                    return; // We have been destroyed!
                this.$gadgetRender.html(template);
                this.drawCharts();
                this.modifyVisiblityByRenderSize();
            };
            HeatMapRender.prototype.drawCharts = function () {
                if (!this.$gadgetRender)
                    return; // We have been destroyed!
                //Handle any older gadget instances if any. Handles the 
                //setting default values for new settings. When old instances
                //are saved the new gadgets parameters are saved in gadgetXML.
                this.updateChartVersion();
                //Clear AmCharts on the page.
                this.clearBarchart();
                var autoColor = this.getHandler().byName(Settings.Gadget.AutoColor.name).toLowerCase();
                var cutOff1 = this.getHandler().byName(Settings.Gadget.Cutoff1.name);
                var cutOff2 = this.getHandler().byName(Settings.Gadget.Cutoff2.name);
                var cutOff3 = this.getHandler().byName(Settings.Gadget.Cutoff3.name);
                var showTotal = this.getHandler().byName(Settings.Gadget.ShowTotal.name);
                //Older gadgets will not have this setting. Hence handle nulls
                showTotal = _.isUndefined(showTotal) || _.isNull(showTotal) ? 'true' : showTotal.toLowerCase();
                var dataPoints = $.extend(true, {}, this.gadget.dataSet.ChartingData.DataPoints); // Deep copy of data
                //Get the max and min values among the data points.
                var max = ISOGadgetsCommon.GadgetHelper.getSignedFormattedNumber(this.gadget.dataSet.ChartingData.Max.Value);
                var min = ISOGadgetsCommon.GadgetHelper.getSignedFormattedNumber(this.gadget.dataSet.ChartingData.Min.Value);
                var chartPoints = _.toArray(dataPoints);
                var dps = [];
                var values = [];
                for (var i = 0; i < chartPoints.length; i++) {
                    var chartPoint = { "SeriesLabel": chartPoints[i][0][Dashboards.Models.ChartingDataGadget.AxisLabelIdx] };
                    for (var j = 0; j < _.size(chartPoints[i]); j++) {
                        var value = ISOGadgetsCommon.GadgetHelper.getSignedFormattedNumber(chartPoints[i][j][Dashboards.Models.ChartingDataGadget.ValueIdx]);
                        chartPoint['value' + j] = i18n.formatNumber(value);
                        chartPoint['hour' + j] = 1;
                        chartPoint['color' + j] = autoColor === 'true' ? this.calculateColor(value, max, min) : this.getColor(value, parseFloat(cutOff1), parseFloat(cutOff2), parseFloat(cutOff3));
                        chartPoint['date' + j] = chartPoints[i][j][Dashboards.Models.HeatMap.PointLabelIdx];
                        values.push(value);
                    }
                    dps.push(chartPoint);
                }
                ;
                var legend = " ";
                _.each(this.gadget.seriesMap, function (series) {
                    legend += series.title;
                });
                //////////////////////////////////////////////////
                ///Populate the total div to display total of all values.
                //In addition, resize the chart area without which chart
                //will go out of the gadget. Chart is resized based on renderer
                //height and height of total div area.
                /////////////////////////////////////////////////////
                var $total_area = this.$gadgetRender.find('#totalvalue');
                var total = _.reduce(values, function (memo, num) { return memo + Number(num); }, 0);
                var totalText = showTotal === 'true' ? legend + ',' + i18n.loc.s('ISO50001Gadgets', 'Gadget_Total') + ': ' + i18n.formatNumber(total, 2) : legend;
                $total_area.html(totalText);
                $total_area.prop('title', totalText);
                var $legend_gradient = this.$gadgetRender.find('#legendGradient');
                //Find out position of bar from user settings and set the bar options
                //appropriately.
                this.clearBarchart();
                var $chart_area = this.$gadgetRender.find('#heatmap');
                $chart_area.height(this.$gadgetRender.height() - $total_area.height() - $legend_gradient.height() - 20);
                this.barchart = this.getHeatMap(dps, legend.trim());
                this.barchart.write($chart_area[0]);
                this.setGradient(values);
            };
            HeatMapRender.prototype.clearBarchart = function () {
                if (!(_.isUndefined(this.barchart) || _.isNull(this.barchart))) {
                    this.barchart.clear();
                    this.barchart = null;
                }
            };
            ///////////////////////////////////////////////////////////////////////
            //Function to take care of gadget upgrade case. Compares the instance//
            //version with the gadgets current version and takes actions like //
            //setting default values of newly introduced gadget parameters//
            ///////////////////////////////////////////////////////////////////////
            HeatMapRender.prototype.updateChartVersion = function () {
                var instanceVersion = Number(this.getHandler().byName(Settings.Gadget.Version.name));
                if (instanceVersion < this.chartVersion) {
                    //Set default values for newly added config settings.
                    this.getHandler().setting(Settings.Gadget.Version, this.chartVersion.toString());
                }
            };
            /////////////////////////////////////////////////////////////
            //Get the color based on user color configuration.
            /////////////////////////////////////////////////////////////
            HeatMapRender.prototype.getColor = function (value, cutOff1, cutOff2, cutOff3) {
                if (_.isUndefined(value) || _.isNull(value) || _.isNaN(value)) {
                    //not available
                    return "#D0D3D4";
                }
                if (value < cutOff1) {
                    return "#0000FF"; //blue
                }
                else if (value >= cutOff1 && value < cutOff2) {
                    return "#00FF00"; //green
                }
                else if (value >= cutOff2 && value < cutOff3) {
                    return "#FFFF00";
                }
                else if (value >= cutOff3) {
                    return "#FF0000";
                }
            };
            /////////////////////////////////////////////////////////////
            //Auto calculate color based on value, max and min in the range.
            /////////////////////////////////////////////////////////////
            HeatMapRender.prototype.calculateColor = function (dataValue, maxValue, minValue) {
                if (_.isUndefined(dataValue) || _.isNull(dataValue) || _.isNaN(dataValue))
                    return "#D0D3D4"; //not available
                var value = ((dataValue - minValue) / (maxValue - minValue));
                var h = Math.round((1.0 - value) * 240);
                return _.isFinite(h) ? "hsl(" + h + ", 100%, 50%)" : "#000";
            };
            /////////////////////////////////////////////////////////////
            //Perform color calculation for an array of values. Used for legend.
            /////////////////////////////////////////////////////////////
            HeatMapRender.prototype.calculateLegendColors = function (dataValues) {
                //Colors change based on gadget settings (auto color or not)
                //hence get the gadget settings.
                var autoColor = this.getHandler().byName(Settings.Gadget.AutoColor.name).toLowerCase();
                var cutOff1 = this.getHandler().byName(Settings.Gadget.Cutoff1.name);
                var cutOff2 = this.getHandler().byName(Settings.Gadget.Cutoff2.name);
                var cutOff3 = this.getHandler().byName(Settings.Gadget.Cutoff3.name);
                var max = ISOGadgetsCommon.GadgetHelper.getSignedFormattedNumber(this.gadget.dataSet.ChartingData.Max.Value);
                var min = ISOGadgetsCommon.GadgetHelper.getSignedFormattedNumber(this.gadget.dataSet.ChartingData.Min.Value);
                //Loop though all data values and get color codes.
                var hslColors = [];
                for (var index = 0; index < dataValues.length; index++) {
                    var color = autoColor === 'true' ? this.calculateColor(dataValues[index], max, min) : this.getColor(dataValues[index], parseFloat(cutOff1), parseFloat(cutOff2), parseFloat(cutOff3));
                    hslColors.push(color);
                }
                return hslColors;
            };
            /////////////////////////////////////////////////////////////
            //Sets the gradient for given data values.
            /////////////////////////////////////////////////////////////
            HeatMapRender.prototype.setGradient = function (values) {
                var $heatmaplegendgradient = this.$gadgetRender.find('#legendGradient');
                var $heatmaplegend = this.$gadgetRender.find('#legend');
                //first let us remove all nulls from the given set of values and sort them.            
                var dataValues = _.sortBy(values, function (num) { return !_.isNumber(num) ? -1 : num; });
                //Get the color codes from given values and then add the linear-gradient background style
                var sortedHslColors = this.calculateLegendColors(dataValues);
                var gradientCss = '(left';
                for (var i = 0; i < sortedHslColors.length; ++i) {
                    gradientCss += ', ' + sortedHslColors[i];
                }
                gradientCss += ')';
                $heatmaplegendgradient.css('background', '-webkit-linear-gradient' + gradientCss);
                $heatmaplegendgradient.css('background', '-moz-linear-gradient' + gradientCss);
                $heatmaplegendgradient.css('background', '-o-linear-gradient' + gradientCss);
                $heatmaplegendgradient.css('background', '-ms-linear-gradient' + gradientCss);
                $heatmaplegendgradient.css('background', 'linear-gradient' + gradientCss);
                //Time to add the legend labels. For this we divide the legend width 
                //to max intervals (5) and then add lable for each interval.
                var legendWidth = $heatmaplegendgradient.outerWidth();
                var maxIntervals = 5;
                var intervalIndex = dataValues.length / maxIntervals; //Interval within the list of values to consider for legend label
                for (var i = 0; i <= maxIntervals; ++i) {
                    var offset = i * legendWidth / maxIntervals;
                    if (i > 0 && i < maxIntervals) {
                        offset -= 0.5;
                    }
                    else if (i == maxIntervals) {
                        offset -= 1;
                    }
                    $heatmaplegend.append($('<div>').css({
                        'position': 'absolute',
                        'left': offset + 'px',
                        'top': '15px',
                        'width': '1px',
                        'height': '3px',
                        'background': 'black'
                    }));
                    //Get the legend label value from the list of data values. This is based in interval index.                
                    var value = dataValues[Math.round(i * intervalIndex) == 0 ? 0 : Math.round(i * intervalIndex) - 1];
                    $heatmaplegend.append($('<div>').css({
                        'position': 'absolute',
                        'left': (offset - 5) + 'px',
                        'top': '18px',
                        'width': '10px',
                        'text-align': 'center'
                    }).html(_.isNumber(value) ? i18n.formatNumber(value) : "null"));
                }
            };
            /////////////////////////////////////////////////////////////
            //Gets the heat map chart for given data series.
            /////////////////////////////////////////////////////////////
            HeatMapRender.prototype.getHeatMap = function (data, series) {
                var serialChart = new AmCharts.AmSerialChart();
                serialChart.dataProvider = data;
                serialChart.decimalSeparator = i18n.numberFormat.decimalDelimiter;
                serialChart.thousandsSeparator = i18n.numberFormat.thousandDelimiter;
                var valueAxis = new AmCharts.ValueAxis();
                valueAxis.title = i18n.loc.s('ISO50001Gadgets', 'Hour_Of_Day');
                valueAxis.duration = "mm";
                valueAxis.axisAlpha = 0.3;
                valueAxis.gridAlpha = 0;
                valueAxis.stackType = "regular"; // we use stacked graphs to make color fills
                serialChart.addValueAxis(valueAxis);
                for (var h = 0; h <= 23; h++) {
                    var amColGraph = new AmCharts.AmGraph();
                    amColGraph.balloonText = series + "<br>[[date" + h + "]]: [[value" + h + "]]";
                    amColGraph.fillAlphas = 1;
                    amColGraph.lineAlpha = 0;
                    amColGraph.type = "column";
                    amColGraph.colorField = "color" + h;
                    amColGraph.valueField = "hour" + h;
                    serialChart.addGraph(amColGraph);
                }
                serialChart.columnWidth = 1;
                serialChart.categoryField = "SeriesLabel";
                serialChart.categoryAxis.gridPosition = "start";
                serialChart.categoryAxis.gridAlpha = 0;
                serialChart.categoryAxis.axisAlpha = 0;
                serialChart.categoryAxis.position = "left";
                serialChart.categoryAxis.labelRotation = 90;
                serialChart.categoryAxis.tickLength = 1;
                serialChart.export = {
                    "enabled": true,
                    "libs": { "autoLoad": false },
                    "fileName": series,
                    "menu": [{
                            "class": "export-main",
                            "icon": "export_16.png",
                            "menu": ["CSV", "XLSX"]
                        }],
                    "processData": function (data) {
                        var formattedData = [];
                        var dtHeader = i18n.loc.s('ISO50001Gadgets', 'DateTime');
                        var hrHeader = i18n.loc.s('ISO50001Gadgets', 'Hour');
                        _.each(data, function (item) {
                            var chartPoint = {};
                            chartPoint[dtHeader] = item.SeriesLabel;
                            _.mapObject(item, function (val, key) {
                                if (key.startsWith('value')) {
                                    chartPoint[key.replace('value', hrHeader)] = val;
                                }
                                return val; //just return the val since we do not want to modify existing item.
                            });
                            formattedData.push(chartPoint);
                        });
                        return formattedData;
                    }
                };
                return serialChart;
            };
            HeatMapRender.RenderTemplateUri = 'Content/Gadgets/HeatMap/HeatMap.html';
            return HeatMapRender;
        }(Views.ViewPeriodChartRender));
        Views.HeatMapRender = HeatMapRender;
    })(Views = Dashboards.Views || (Dashboards.Views = {}));
})(Dashboards || (Dashboards = {}));
// Register the gadget type
Dashboards.Controllers.GadgetType.RegisterDefinition({
    typeId: Dashboards.Models.HeatMap.TypeId,
    create: Dashboards.Models.HeatMap.CreateInstance,
    resourceSet: 'ISO50001Gadgets'
});
//# sourceMappingURL=HeatMap.js.map