/* *
 *
 *  (c) 2010-2021 Torstein Honsi
 *
 *  License: www.highcharts.com/license
 *
 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
 *
 * */
'use strict';
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
import A from '../../Core/Animation/AnimationUtilities.js';
var setAnimation = A.setAnimation;
import Point from '../../Core/Series/Point.js';
import U from '../../Core/Utilities.js';
var addEvent = U.addEvent, defined = U.defined, extend = U.extend, isNumber = U.isNumber, pick = U.pick, relativeLength = U.relativeLength;
/* *
 *
 *  Class
 *
 * */
var PiePoint = /** @class */ (function (_super) {
    __extends(PiePoint, _super);
    function PiePoint() {
        /* *
         *
         *  Properties
         *
         * */
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.labelDistance = void 0;
        _this.options = void 0;
        _this.series = void 0;
        return _this;
    }
    /* *
     *
     *  Functions
     *
     * */
    /* eslint-disable valid-jsdoc */
    /**
     * Extendable method for getting the path of the connector between the
     * data label and the pie slice.
     * @private
     */
    PiePoint.prototype.getConnectorPath = function () {
        var labelPosition = this.labelPosition, options = this.series.options.dataLabels, predefinedShapes = this.connectorShapes;
        var connectorShape = options.connectorShape;
        // find out whether to use the predefined shape
        if (predefinedShapes[connectorShape]) {
            connectorShape = predefinedShapes[connectorShape];
        }
        return connectorShape.call(this, {
            // pass simplified label position object for user's convenience
            x: labelPosition.final.x,
            y: labelPosition.final.y,
            alignment: labelPosition.alignment
        }, labelPosition.connectorPosition, options);
    };
    /**
     * @private
     */
    PiePoint.prototype.getTranslate = function () {
        return this.sliced ? this.slicedTranslation : {
            translateX: 0,
            translateY: 0
        };
    };
    /**
     * @private
     */
    PiePoint.prototype.haloPath = function (size) {
        var shapeArgs = this.shapeArgs;
        return this.sliced || !this.visible ?
            [] :
            this.series.chart.renderer.symbols.arc(shapeArgs.x, shapeArgs.y, shapeArgs.r + size, shapeArgs.r + size, {
                // Substract 1px to ensure the background is not bleeding
                // through between the halo and the slice (#7495).
                innerR: shapeArgs.r - 1,
                start: shapeArgs.start,
                end: shapeArgs.end
            });
    };
    /**
     * Initialize the pie slice.
     * @private
     */
    PiePoint.prototype.init = function () {
        var _this = this;
        _super.prototype.init.apply(this, arguments);
        this.name = pick(this.name, 'Slice');
        // add event listener for select
        var toggleSlice = function (e) {
            _this.slice(e.type === 'select');
        };
        addEvent(this, 'select', toggleSlice);
        addEvent(this, 'unselect', toggleSlice);
        return this;
    };
    /**
     * Negative points are not valid (#1530, #3623, #5322)
     * @private
     */
    PiePoint.prototype.isValid = function () {
        return isNumber(this.y) && this.y >= 0;
    };
    /**
     * Toggle the visibility of the pie slice.
     * @private
     *
     * @param {boolean} vis
     * Whether to show the slice or not. If undefined, the visibility is
     * toggled.
     */
    PiePoint.prototype.setVisible = function (vis, redraw) {
        var _this = this;
        var series = this.series, chart = series.chart, ignoreHiddenPoint = series.options.ignoreHiddenPoint;
        redraw = pick(redraw, ignoreHiddenPoint);
        if (vis !== this.visible) {
            // If called without an argument, toggle visibility
            this.visible = this.options.visible = vis =
                typeof vis === 'undefined' ? !this.visible : vis;
            // update userOptions.data
            series.options.data[series.data.indexOf(this)] =
                this.options;
            // Show and hide associated elements. This is performed
            // regardless of redraw or not, because chart.redraw only
            // handles full series.
            ['graphic', 'dataLabel', 'connector', 'shadowGroup'].forEach(function (key) {
                if (_this[key]) {
                    _this[key][vis ? 'show' : 'hide'](vis);
                }
            });
            if (this.legendItem) {
                chart.legend.colorizeItem(this, vis);
            }
            // #4170, hide halo after hiding point
            if (!vis && this.state === 'hover') {
                this.setState('');
            }
            // Handle ignore hidden slices
            if (ignoreHiddenPoint) {
                series.isDirty = true;
            }
            if (redraw) {
                chart.redraw();
            }
        }
    };
    /**
     * Set or toggle whether the slice is cut out from the pie.
     * @private
     *
     * @param {boolean} sliced
     * When undefined, the slice state is toggled.
     *
     * @param {boolean} [redraw]
     * Whether to redraw the chart. True by default.
     *
     * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
     * Animation options.
     */
    PiePoint.prototype.slice = function (sliced, redraw, animation) {
        var series = this.series, chart = series.chart;
        setAnimation(animation, chart);
        // redraw is true by default
        redraw = pick(redraw, true);
        /**
         * Pie series only. Whether to display a slice offset from the
         * center.
         * @name Highcharts.Point#sliced
         * @type {boolean|undefined}
         */
        // if called without an argument, toggle
        this.sliced = this.options.sliced = sliced =
            defined(sliced) ? sliced : !this.sliced;
        // update userOptions.data
        series.options.data[series.data.indexOf(this)] =
            this.options;
        if (this.graphic) {
            this.graphic.animate(this.getTranslate());
        }
        if (this.shadowGroup) {
            this.shadowGroup.animate(this.getTranslate());
        }
    };
    return PiePoint;
}(Point));
extend(PiePoint.prototype, {
    connectorShapes: {
        // only one available before v7.0.0
        fixedOffset: function (labelPosition, connectorPosition, options) {
            var breakAt = connectorPosition.breakAt, touchingSliceAt = connectorPosition.touchingSliceAt, lineSegment = options.softConnector ? [
                'C',
                // 1st control point (of the curve)
                labelPosition.x +
                    // 5 gives the connector a little horizontal bend
                    (labelPosition.alignment === 'left' ? -5 : 5),
                labelPosition.y,
                2 * breakAt.x - touchingSliceAt.x,
                2 * breakAt.y - touchingSliceAt.y,
                breakAt.x,
                breakAt.y //
            ] : [
                'L',
                breakAt.x,
                breakAt.y
            ];
            // assemble the path
            return ([
                ['M', labelPosition.x, labelPosition.y],
                lineSegment,
                ['L', touchingSliceAt.x, touchingSliceAt.y]
            ]);
        },
        straight: function (labelPosition, connectorPosition) {
            var touchingSliceAt = connectorPosition.touchingSliceAt;
            // direct line to the slice
            return [
                ['M', labelPosition.x, labelPosition.y],
                ['L', touchingSliceAt.x, touchingSliceAt.y]
            ];
        },
        crookedLine: function (labelPosition, connectorPosition, options) {
            var touchingSliceAt = connectorPosition.touchingSliceAt, series = this.series, pieCenterX = series.center[0], plotWidth = series.chart.plotWidth, plotLeft = series.chart.plotLeft, alignment = labelPosition.alignment, radius = this.shapeArgs.r, crookDistance = relativeLength(// % to fraction
            options.crookDistance, 1), crookX = alignment === 'left' ?
                pieCenterX + radius + (plotWidth + plotLeft -
                    pieCenterX - radius) * (1 - crookDistance) :
                plotLeft + (pieCenterX - radius) * crookDistance, segmentWithCrook = [
                'L',
                crookX,
                labelPosition.y
            ];
            var useCrook = true;
            // crookedLine formula doesn't make sense if the path overlaps
            // the label - use straight line instead in that case
            if (alignment === 'left' ?
                (crookX > labelPosition.x || crookX < touchingSliceAt.x) :
                (crookX < labelPosition.x || crookX > touchingSliceAt.x)) {
                useCrook = false;
            }
            // assemble the path
            var path = [['M', labelPosition.x, labelPosition.y]];
            if (useCrook) {
                path.push(segmentWithCrook);
            }
            path.push(['L', touchingSliceAt.x, touchingSliceAt.y]);
            return path;
        }
    }
});
/* *
 *
 *  Default Export
 *
 * */
export default PiePoint;
