/*
Flot plugin for showing an Exegy Management Console style cursor over the plot.

  cursor:
  {
    mode: "drag" or "hover",    // operational mode (default is "hover")
    color: color,               // color of the crosshair (default is "rgba(170, 0, 0, 0.80)")
    lineWidth: number,          // width of the drawn lines (default is 1)
    cursorUpdate: fn() or null, // fn([{index,x_value,y_value}]) called with new cursor data
    highlight: true/false       // true to higlight individual points under the cursor
  }
*/

(function ($)
{
    var options =
        {
            cursor: 
            {
                mode: "hover",
                color: "rgba(170, 0, 0, 0.80)",
                lineWidth: 1,
                cursorUpdate: null,
                highlight: true
            }
        };
    
    function init(plot) 
    {
        var crosshair = -1;
        var dragging = false;
        
        plot.hooks.bindEvents.push(function (plot, eventHolder) 
        {

            eventHolder.mousedown(function (e)
            {
                var c = plot.getOptions().cursor;
                if (c.mode.indexOf("drag") == -1) return;
                dragging = true;
                downormove(e);
            });
            
            eventHolder.mouseout(function (e)
            {
                dragging = false;
                if (crosshair != -1)
                {
                    crosshair = -1;  // hide the cursor
                    if (plot.getOptions().cursor.highlight)
                        plot.unhighlight();
                    plot.triggerRedrawOverlay();
                }
            });

            eventHolder.mouseup(function (e) 
            {
                if (dragging) 
                {
                    dragging = false;
                    if (crosshair != -1) 
                    {
                        crosshair = -1;  // hide the cursor
                        if (plot.getOptions().cursor.highlight)
                            plot.unhighlight();
                        plot.triggerRedrawOverlay();
                    }
                }
            });

            eventHolder.mousemove(downormove);
                    
            function downormove(e) 
            {

                if (dragging || plot.getOptions().cursor.mode.indexOf("hover") != -1)
                { 
                    // Redraw the cursor
                    crosshair = Math.max(0, Math.min(e.pageX - plot.offset().left, plot.width()));
                    plot.triggerRedrawOverlay();
                    
                    // Find the nearest data point to the crosshair in each series
                    var series = plot.getData(),
                        dix = Array(),
                        xval = Array(),
                        mouseX = e.pageX - plot.offset().left;
                   
                    for (i = 0; i < series.length; ++i)
                    {
                        var s = series[i],
                            axisx = s.xaxis,
                            points = s.datapoints.points,
                            ps = s.datapoints.pointsize,
                            smallestDistance = Number.MAX_VALUE;

                        dix[i] = -1;
                        xval[i] = null;
                        if (s.lines.show || s.points.show)
                        {
                            for (j = 0, done=false; j < points.length && !done; j += ps)
                            {
                                var x = points[j];
                                if (x == null) continue;
                                var dx = Math.abs(axisx.p2c(x) - mouseX);
                                if (dx <= smallestDistance) 
                                {
                                    smallestDistance = dx;
                                    dix[i] = j / ps;
                                    xval[i] = x;
                                }
                                else
                                    done = true;
                            }
                        }
                    }
                    
                    // Update the cursor values and highlight specific data point values
                    plot.unhighlight();
                    var f = plot.getOptions(), 
                        c = f.cursor, 
                        updates = [], 
                        total = 0;
                    for (i = 0; i < series.length; ++i)
                    {
                        if (dix[i] >= 0)
                        {
                            var s = series[i];
                            if (!f.series.stack)    // if data series are not stacked 
                            {
                                total = s.data[dix[i]][1];
                                if (c.highlight) plot.highlight(i, dix[i]);
                            } else {                // ...otherwise data are stacked
                                total += s.data[dix[i]][1];
                                if (c.highlight) plot.highlight(i, [xval[i], total]);
                            }
                            updates.push({ index: i, x_value: xval[i], y_value: total });
                        }
                    }
                    if (c.cursorUpdate)
                        c.cursorUpdate(updates);
                }
            }
        });

        plot.hooks.drawOverlay.push(function (plot, ctx)
        {
            var c = plot.getOptions().cursor,
                plotOffset = plot.getPlotOffset();
            
            ctx.save();
            ctx.translate(plotOffset.left, plotOffset.top);

            if (crosshair != -1) 
            {
                ctx.strokeStyle = c.color;
                ctx.lineWidth = c.lineWidth;
                ctx.lineJoin = "round";

                ctx.beginPath();
                ctx.moveTo(crosshair, 0);
                ctx.lineTo(crosshair, plot.height());
                ctx.stroke();
            }
            ctx.restore();
        });
    }
    
    $.plot.plugins.push(
    {
        init: init,
        options: options,
        name: 'xmc.cursor',
        version: '1.0'
    });
})(jQuery);

