function _array_like_to_array(arr, len) {
    if (len == null || len > arr.length) len = arr.length;
    for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
    return arr2;
}
function _array_with_holes(arr) {
    if (Array.isArray(arr)) return arr;
}
function _iterable_to_array_limit(arr, i) {
    var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
    if (_i == null) return;
    var _arr = [];
    var _n = true;
    var _d = false;
    var _s, _e;
    try {
        for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
            _arr.push(_s.value);
            if (i && _arr.length === i) break;
        }
    } catch (err) {
        _d = true;
        _e = err;
    } finally{
        try {
            if (!_n && _i["return"] != null) _i["return"]();
        } finally{
            if (_d) throw _e;
        }
    }
    return _arr;
}
function _non_iterable_rest() {
    throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _sliced_to_array(arr, i) {
    return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
}
function _unsupported_iterable_to_array(o, minLen) {
    if (!o) return;
    if (typeof o === "string") return _array_like_to_array(o, minLen);
    var n = Object.prototype.toString.call(o).slice(8, -1);
    if (n === "Object" && o.constructor) n = o.constructor.name;
    if (n === "Map" || n === "Set") return Array.from(n);
    if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
}
import { select } from "d3-selection";
import { zoomTransform } from "d3-zoom";
import { attrize, stylize } from "@d3plus/dom";
var brushing = false;
/**
    @name zoomControls
    Sets up initial zoom events and controls.
    @private
*/ export default function() {
    var _this = this;
    if (!this._container || !this._zoomGroup) return;
    var height = this._zoomHeight || this._height - this._margin.top - this._margin.bottom, that = this, width = this._zoomWidth || this._width - this._margin.left - this._margin.right;
    this._zoomBehavior.extent([
        [
            0,
            0
        ],
        [
            width,
            height
        ]
    ]).scaleExtent([
        1,
        this._zoomMax
    ]).translateExtent([
        [
            0,
            0
        ],
        [
            width,
            height
        ]
    ]).on("zoom", function(event) {
        return zoomed.bind(_this)(event.transform);
    });
    this._zoomToBounds = zoomToBounds.bind(this);
    var control = select(this._select.node().parentNode).selectAll("div.d3plus-zoom-control").data(this._zoom ? [
        0
    ] : []);
    var controlEnter = control.enter().append("div").attr("class", "d3plus-zoom-control");
    control.exit().remove();
    control = control.merge(controlEnter).style("position", "absolute").style("top", "".concat(this._margin.top, "px")).style("left", "".concat(this._margin.left, "px"));
    controlEnter.append("div").attr("class", "zoom-control zoom-in");
    control.select(".zoom-in").on("click", zoomMath.bind(this, this._zoomFactor)).html("&#65291;");
    controlEnter.append("div").attr("class", "zoom-control zoom-out");
    control.select(".zoom-out").on("click", zoomMath.bind(this, 1 / this._zoomFactor)).html("&#65293;");
    controlEnter.append("div").attr("class", "zoom-control zoom-reset");
    control.select(".zoom-reset").on("click", zoomMath.bind(this, 0)).html("&#8634");
    controlEnter.append("div").attr("class", "zoom-control zoom-brush");
    control.select(".zoom-brush").on("click", function(_event) {
        select(_event.currentTarget).classed("active", !brushing).call(stylize, brushing ? that._zoomControlStyle || {} : that._zoomControlStyleActive || {});
        zoomEvents.bind(that)(!brushing);
    }).html("&#164");
    control.selectAll(".zoom-control").call(stylize, that._zoomControlStyle).on("mouseenter", function(_event) {
        select(_event.currentTarget).call(stylize, that._zoomControlStyleHover || {});
    }).on("mouseleave", function(_event) {
        var el = select(_event.currentTarget);
        el.call(stylize, el.classed("active") ? that._zoomControlStyleActive || {} : that._zoomControlStyle || {});
    });
    this._zoomBrush.extent([
        [
            0,
            0
        ],
        [
            width,
            height
        ]
    ]).filter(function(event) {
        return !event.button && event.detail < 2;
    }).handleSize(this._zoomBrushHandleSize).on("start", brushStart.bind(this)).on("brush", brushBrush.bind(this)).on("end", brushEnd.bind(this));
    var brushGroup = this._container.selectAll("g.brush").data([
        0
    ]);
    this._brushGroup = brushGroup.enter().append("g").attr("class", "brush").merge(brushGroup).call(this._zoomBrush);
    zoomEvents.bind(this)();
    if (this._renderTiles) this._renderTiles(zoomTransform(this._container.node()), 0);
}
/**
    @name zoomEvents
    Handles adding/removing zoom event listeners.
    @private
*/ function zoomEvents() {
    var brush = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : false;
    brushing = brush;
    if (brushing) this._brushGroup.style("display", "inline");
    else this._brushGroup.style("display", "none");
    if (!brushing && this._zoom) {
        this._container.call(this._zoomBehavior);
        if (!this._zoomScroll) {
            this._container.on("wheel.zoom", null);
        }
        if (!this._zoomPan) {
            this._container.on("mousedown.zoom mousemove.zoom", null).on("touchstart.zoom touchmove.zoom touchend.zoom touchcancel.zoom", null);
        }
    } else {
        this._container.on(".zoom", null);
    }
}
/**
    @name zoomed
    Handles events dispatched from this._zoomBehavior
    @param transform
    @private
*/ function zoomed() {
    var transform = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : false, duration = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 0;
    if (this._zoomGroup) {
        if (!duration) this._zoomGroup.attr("transform", transform);
        else this._zoomGroup.transition().duration(duration).attr("transform", transform);
    }
    if (this._renderTiles) this._renderTiles(zoomTransform(this._container.node()), duration);
}
/**
    @name zoomMath
    Zooms in or out based on the provided multiplier.
    @param factor @private
*/ function zoomMath() {
    var factor = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : 0;
    if (!this._container) return;
    var center = this._zoomBehavior.extent().bind(document)()[1].map(function(d) {
        return d / 2;
    }), scaleExtent = this._zoomBehavior.scaleExtent(), t = zoomTransform(this._container.node());
    if (!factor) {
        t.k = scaleExtent[0];
        t.x = 0;
        t.y = 0;
    } else {
        var translate0 = [
            (center[0] - t.x) / t.k,
            (center[1] - t.y) / t.k
        ];
        t.k = Math.min(scaleExtent[1], t.k * factor);
        if (t.k <= scaleExtent[0]) {
            t.k = scaleExtent[0];
            t.x = 0;
            t.y = 0;
        } else {
            t.x += center[0] - (translate0[0] * t.k + t.x);
            t.y += center[1] - (translate0[1] * t.k + t.y);
        }
    }
    zoomed.bind(this)(t, this._duration);
}
/**
    @name zoomToBounds
    Zooms to given bounds.
    @param bounds
    @private
*/ function zoomToBounds(bounds) {
    var duration = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : this._duration;
    var scaleExtent = this._zoomBehavior.scaleExtent(), t = zoomTransform(this._container.node());
    if (bounds) {
        var _this__zoomBehavior_translateExtent_ = _sliced_to_array(this._zoomBehavior.translateExtent()[1], 2), width = _this__zoomBehavior_translateExtent_[0], height = _this__zoomBehavior_translateExtent_[1], dx = bounds[1][0] - bounds[0][0], dy = bounds[1][1] - bounds[0][1];
        var k = Math.min(scaleExtent[1], 1 / Math.max(dx / width, dy / height));
        var xMod, yMod;
        if (dx / dy < width / height) {
            k *= (height - this._zoomPadding * 2) / height;
            xMod = (width - dx * k) / 2 / k;
            yMod = this._zoomPadding / k;
        } else {
            k *= (width - this._zoomPadding * 2) / width;
            yMod = (height - dy * k) / 2 / k;
            xMod = this._zoomPadding / k;
        }
        t.x = (t.x - bounds[0][0] + xMod) * (t.k * k / t.k);
        t.y = (t.y - bounds[0][1] + yMod) * (t.k * k / t.k);
        t.k *= k;
        if (t.x > 0) t.x = 0;
        else if (t.x < width * -t.k + width) t.x = width * -t.k + width;
        if (t.y > 0) t.y = 0;
        else if (t.y < height * -t.k + height) t.y = height * -t.k + height;
    } else {
        t.k = scaleExtent[0];
        t.x = 0;
        t.y = 0;
    }
    zoomed.bind(this)(t, duration);
}
/**
    Triggered on brush "brush".
    @private
*/ function brushBrush() {
    brushStyle.bind(this)();
}
/**
    Triggered on brush "end".
    @private
*/ function brushEnd(event) {
    if (!event.selection) return; // Only transition after input.
    this._brushGroup.call(this._zoomBrush.move, null);
    zoomToBounds.bind(this)(event.selection);
}
/**
    Triggered on brush "start".
    @private
*/ function brushStart() {
    brushStyle.bind(this)();
}
/**
    Overrides the default brush styles.
    @private
*/ function brushStyle() {
    this._brushGroup.selectAll(".selection").call(attrize, this._zoomBrushSelectionStyle || {});
    this._brushGroup.selectAll(".handle").call(attrize, this._zoomBrushHandleStyle || {});
}
