/**
* Copyright 2012-2017, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/


'use strict';

var Fx = require('../../plots/cartesian/graph_interact');
var ErrorBars = require('../../components/errorbars');
var Color = require('../../components/color');


module.exports = function hoverPoints(pointData, xval, yval, hovermode) {
    var cd = pointData.cd,
        trace = cd[0].trace,
        t = cd[0].t,
        xa = pointData.xa,
        ya = pointData.ya,
        barDelta = (hovermode === 'closest') ?
            t.barwidth / 2 :
            t.bargroupwidth / 2,
        barPos;

    if(hovermode !== 'closest') barPos = function(di) { return di.p; };
    else if(trace.orientation === 'h') barPos = function(di) { return di.y; };
    else barPos = function(di) { return di.x; };

    var dx, dy;
    if(trace.orientation === 'h') {
        dx = function(di) {
            // add a gradient so hovering near the end of a
            // bar makes it a little closer match
            return Fx.inbox(di.b - xval, di.x - xval) + (di.x - xval) / (di.x - di.b);
        };
        dy = function(di) {
            var centerPos = barPos(di) - yval;
            return Fx.inbox(centerPos - barDelta, centerPos + barDelta);
        };
    }
    else {
        dy = function(di) {
            return Fx.inbox(di.b - yval, di.y - yval) + (di.y - yval) / (di.y - di.b);
        };
        dx = function(di) {
            var centerPos = barPos(di) - xval;
            return Fx.inbox(centerPos - barDelta, centerPos + barDelta);
        };
    }

    var distfn = Fx.getDistanceFunction(hovermode, dx, dy);
    Fx.getClosest(cd, distfn, pointData);

    // skip the rest (for this trace) if we didn't find a close point
    if(pointData.index === false) return;

    // the closest data point
    var di = cd[pointData.index],
        mc = di.mcc || trace.marker.color,
        mlc = di.mlcc || trace.marker.line.color,
        mlw = di.mlw || trace.marker.line.width;
    if(Color.opacity(mc)) pointData.color = mc;
    else if(Color.opacity(mlc) && mlw) pointData.color = mlc;

    var size = (trace.base) ? di.b + di.s : di.s;
    if(trace.orientation === 'h') {
        pointData.x0 = pointData.x1 = xa.c2p(di.x, true);
        pointData.xLabelVal = size;

        pointData.y0 = ya.c2p(barPos(di) - barDelta, true);
        pointData.y1 = ya.c2p(barPos(di) + barDelta, true);
        pointData.yLabelVal = di.p;
    }
    else {
        pointData.y0 = pointData.y1 = ya.c2p(di.y, true);
        pointData.yLabelVal = size;

        pointData.x0 = xa.c2p(barPos(di) - barDelta, true);
        pointData.x1 = xa.c2p(barPos(di) + barDelta, true);
        pointData.xLabelVal = di.p;
    }

    if(di.tx) pointData.text = di.tx;

    ErrorBars.hoverInfo(di, trace, pointData);

    return [pointData];
};

@@ -571,126 +571,18 @@
 a.ya
-,%0A        barDelta = (hovermode === 'closest') ?%0A            t.barwidth / 2 :%0A            t.bargroupwidth / 2,%0A       
+;%0A%0A    var
  bar
@@ -586,17 +586,16 @@
 barPos;%0A
-%0A
     if(h
@@ -787,16 +787,184 @@
 .x; %7D;%0A%0A
+    var barDelta = (hovermode === 'closest') ?%0A        function(i) %7B return (t.barwidth%5Bi%5D %7C%7C t.barwidth) / 2; %7D :%0A        function() %7B return t.bargroupwidth / 2; %7D;%0A%0A
     var 
@@ -1259,32 +1259,35 @@
 dy = function(di
+, i
 ) %7B%0A            
@@ -1317,24 +1317,61 @@
 di) - yval;%0A
+            var delta = barDelta(i);%0A
             
@@ -1390,36 +1390,33 @@
 box(centerPos - 
-barD
+d
 elta, centerPos 
@@ -1409,36 +1409,33 @@
 ta, centerPos + 
-barD
+d
 elta);%0A        %7D
@@ -1595,32 +1595,35 @@
 dx = function(di
+, i
 ) %7B%0A            
@@ -1653,24 +1653,61 @@
 di) - xval;%0A
+            var delta = barDelta(i);%0A
             
@@ -1734,20 +1734,17 @@
 erPos - 
-barD
+d
 elta, ce
@@ -1753,20 +1753,17 @@
 erPos + 
-barD
+d
 elta);%0A 
@@ -2037,16 +2037,16 @@
 var 
-di = cd%5B
+index = 
 poin
@@ -2056,16 +2056,39 @@
 ta.index
+,%0A        di = cd%5Bindex
 %5D,%0A     
@@ -2559,32 +2559,39 @@
 s(di) - barDelta
+(index)
 , true);%0A       
@@ -2626,32 +2626,39 @@
 s(di) + barDelta
+(index)
 , true);%0A       
@@ -2841,32 +2841,39 @@
 s(di) - barDelta
+(index)
 , true);%0A       
@@ -2916,16 +2916,23 @@
 barDelta
+(index)
 , true);

generalize bar delta computation