'use strict';

var Lib = require('../../lib');
var Axes = require('../../plots/cartesian/axes');

var draw = require('./draw').draw;


module.exports = function calcAutorange(gd) {
    var fullLayout = gd._fullLayout;
    var annotationList = Lib.filterVisible(fullLayout.annotations);

    if(annotationList.length && gd._fullData.length) {
        return Lib.syncOrAsync([draw, annAutorange], gd);
    }
};

function annAutorange(gd) {
    var fullLayout = gd._fullLayout;

    // find the bounding boxes for each of these annotations'
    // relative to their anchor points
    // use the arrow and the text bg rectangle,
    // as the whole anno may include hidden text in its bbox
    Lib.filterVisible(fullLayout.annotations).forEach(function(ann) {
        var xa = Axes.getFromId(gd, ann.xref);
        var ya = Axes.getFromId(gd, ann.yref);
        var xRefType = Axes.getRefType(ann.xref);
        var yRefType = Axes.getRefType(ann.yref);

        ann._extremes = {};
        if(xRefType === 'range') calcAxisExpansion(ann, xa);
        if(yRefType === 'range') calcAxisExpansion(ann, ya);
    });
}

function calcAxisExpansion(ann, ax) {
    var axId = ax._id;
    var letter = axId.charAt(0);
    var pos = ann[letter];
    var apos = ann['a' + letter];
    var ref = ann[letter + 'ref'];
    var aref = ann['a' + letter + 'ref'];
    var padplus = ann['_' + letter + 'padplus'];
    var padminus = ann['_' + letter + 'padminus'];
    var shift = {x: 1, y: -1}[letter] * ann[letter + 'shift'];
    var headSize = 3 * ann.arrowsize * ann.arrowwidth || 0;
    var headPlus = headSize + shift;
    var headMinus = headSize - shift;
    var startHeadSize = 3 * ann.startarrowsize * ann.arrowwidth || 0;
    var startHeadPlus = startHeadSize + shift;
    var startHeadMinus = startHeadSize - shift;
    var extremes;

    if(aref === ref) {
        // expand for the arrowhead (padded by arrowhead)
        var extremeArrowHead = Axes.findExtremes(ax, [ax.r2c(pos)], {
            ppadplus: headPlus,
            ppadminus: headMinus
        });
        // again for the textbox (padded by textbox)
        var extremeText = Axes.findExtremes(ax, [ax.r2c(apos)], {
            ppadplus: Math.max(padplus, startHeadPlus),
            ppadminus: Math.max(padminus, startHeadMinus)
        });
        extremes = {
            min: [extremeArrowHead.min[0], extremeText.min[0]],
            max: [extremeArrowHead.max[0], extremeText.max[0]]
        };
    } else {
        startHeadPlus = apos ? startHeadPlus + apos : startHeadPlus;
        startHeadMinus = apos ? startHeadMinus - apos : startHeadMinus;
        extremes = Axes.findExtremes(ax, [ax.r2c(pos)], {
            ppadplus: Math.max(padplus, headPlus, startHeadPlus),
            ppadminus: Math.max(padminus, headMinus, startHeadMinus)
        });
    }

    ann._extremes[axId] = extremes;
}
