// (C) Copyright 2020 Hewlett-Packard Enterprise Company, L.P.

define(['hp/core/Style', 'jquery', 'lib/jquery.flot.selection',
    'lib/jquery.flot.fillbetween', 'lib/jquery.flot.time'],
function(style) {
    (function($) {
        // jQuery plugin definition
        function hpTimeSeries (placeholderElem, selectionElem, data, extraOptions) {

            function showTooltip(x, y, contents) {
                $('<div id="flot_chart_tooltip">' + contents + '</div>').css( {
                    top: y - 25,
                    left: x + 13
                }).appendTo("body").fadeIn(200);
            }

            var async = extraOptions.async,// true if data is to be retrieved asynchronously
                isDragging = false,
                self =this;
            //options for the Placeholder graph
            var plotOptions = {
                series: {
                    lines: { show: true, lineWidth: 5 },
                    points: { show: false},
                    shadowSize: 0
                },
                xaxis: { mode: "time", tickLength: 5 },
                colors: style.graphColors(),
                selection: { mode: "x" },
                grid: { 
                    hoverable: true,
                    borderWidth: 1,
                    borderColor: style.plotGuideColor()
                },
                legend: {
                    show: false
                }
            }; 

            $.extend(true, plotOptions, extraOptions);
            //options for the Selection graph
            var overviewOptions = {
                series: {
                    lines: { show: true, lineWidth: 1 },
                    shadowSize: 0
                },
                xaxis: { mode: "time", tickLength: 5},
                yaxis: { ticks: [], min: 0, autoscaleMargin: 0.1 },
                selection: { mode: "x" },
                colors: style.graphColors(),
                grid: { 
                    hoverable: true,
                    clickable: true,
                    borderWidth: 1,
                    borderColor: style.plotGuideColor()
                },
                legend:{show:false}
            };

            var plot = $.plot(placeholderElem, data, plotOptions);

            var overview = $.plot(selectionElem, data, overviewOptions); 

            // now connect the two
            placeholderElem.bind("plotselected", function(event, ranges) {
                // do the zooming
                plot = $.plot(placeholderElem, data, $.extend(true, {}, plotOptions, {
                    xaxis : {
                        min : ranges.xaxis.from,
                        max : ranges.xaxis.to
                    }
                }));
                // don't fire event on the overview to prevent eternal loop
                overview.setSelection(ranges, true);
            });

            selectionElem.bind("plotselected", function(event, ranges) {
                plot.setSelection(ranges);
            });
             
            //bind the placeholder chart with plothover
            placeholderElem.bind("plothover", function (event, pos, item) {
                if (item) {
                    $("#flot_chart_tooltip").remove();
                    showTooltip(item.pageX, item.pageY, item.datapoint[1]);
                } else {
                    $("#flot_chart_tooltip").remove();
                }
            });

            // massage inline CSS so we can control with stylsheets
            $('.tickLabels, .tickLabels .xAxis, .tickLabels .yAxis', placeholderElem).
                removeAttr('style');
                
            // unset legend customizations
            if (plotOptions.legend.hasOwnProperty('container')) {
                $('> table', plotOptions.legend.container).removeAttr('style');
                $('.legendColorBox > div > div', plotOptions.legend.container).unwrap();
                // re-order legend table columns
                $('table tr', plotOptions.legend.container).each(function(index, row) {
                    // remove first cell and re-append
                    var cell = $('td', row).first();
                    cell.detach();
                    $(row).append(cell);
                });
            }
            
            //we need to detect if it was a click or a selection so that we may proceed to
            //display the correct data
            $(selectionElem).mousedown(function(e) {
                var x = e.clientX;
                var y = e.clientY;
                var minMovement = 3;
                $(window).mousemove(function(e) {
                    if(Math.abs(e.clientX - x) > minMovement || Math.abs(e.clientY - y) > minMovement) {
                        isDragging = true;
                        $(window).unbind("mousemove");
                    }
                });
            }).mouseup(function() {
                $(window).unbind("mousemove");
            });

            // if mouse isn't dragged a "plotClic" event will be triggered
            selectionElem.bind("plotclick", function(event, pos, item) {
                if(!isDragging) {
                    if(item) {
                        if(async) {
                            selectionElem.trigger("timeSeriesClicked", item);
                        } else {
                            var dataPoint = item.series.data[item.dataIndex];
                            if(dataPoint[0]) {
                                var beginning = new Date(dataPoint[0]), end = new Date(dataPoint[0]);
                                beginning.setHours(0, 0, 0, 0);
                                end.setHours(23, 59, 59, 999);
                                var ranges = {
                                    xaxis : {
                                        from : beginning.getTime(),
                                        to : end.getTime()
                                    }
                                };
                                plot.setSelection(ranges);
                            }
                        }
                    }
                }
                isDragging = false;
            });
            selectionElem.bind('plotselected',function(event,ranges){
                if(async){
                    selectionElem.trigger("timeSeriesSelected",ranges);
                }
            });
            
            /**
             * finds the minimum and maximum timestamps in a set of data
             */
            function generateRanges(dataSet) {
                var min, max = 0;
                for(var i = 0, length = dataSet.length; i < length; i += 1) {
                    var currentDataSet = dataSet[i];
                    if(currentDataSet.hasOwnProperty("data")) {
                        var currentDataArray = currentDataSet.data;
                        for(var j = 0, arrayLen = currentDataArray.length; j < arrayLen; j += 1) {
                            var currentData = currentDataArray[j][0];
                            if(currentData < min || !min) {
                                min = currentData;
                            }
                            else if(currentData > max) {
                                max = currentData;
                            }
                        }
                    }
                }
                var ranges = {
                    xaxis : {
                        from : min,
                        to : max
                    }
                };

                return ranges;
            }

            /**
             * updates the placeholder graph, can be used for populating this graph
             * with data obtained in an async. fashion
             * @param {object} this is the data Array, MUST CONTAIN THE SAME PROPERTIES AS
             * THE ORIGINAL DATA SET (including label and options)
             */
            this.updatePlaceholder = function(updatedData){
                plot.setData(updatedData);
                plot.setupGrid();
                plot.draw();
                
                // don't fire event on the overview to prevent eternal loop
                overview.setSelection(generateRanges(updatedData), true);
            };
            this.updatePlots = function(updatedData){
                overview.setData(updatedData);
                overview.setupGrid();
                plot.draw();
                self.updatePlaceholder(updatedData);
            };
        }
        
        $.hpTimeSeries = function(placeholderElem,selectionElem, data, extraOptions) {

            var TimeSeries = new hpTimeSeries(placeholderElem,selectionElem, data, extraOptions);
            //return this instance so we don't lose our reference to this chart
            return TimeSeries;
        };
    }(jQuery));
});
