import { __assign, __rest, __spreadArrays } from "tslib";
import React, { useContext, useRef, useState, useEffect } from 'react';
import classNames from 'classnames';
import { ConfigContext } from '../config-provider/config-context';
import { getPrefixCls } from '../_utils/general';
import Tooltip from '../tooltip';
var Slider = React.forwardRef(function (props, ref) {
    var _a, _b, _c;
    var _d = props.defaultValue, defaultValue = _d === void 0 ? 0 : _d, _e = props.min, min = _e === void 0 ? 0 : _e, _f = props.max, max = _f === void 0 ? 100 : _f, _g = props.direction, direction = _g === void 0 ? 'horizontal' : _g, _h = props.dots, dots = _h === void 0 ? false : _h, _j = props.step, step = _j === void 0 ? 1 : _j, _k = props.disabled, disabled = _k === void 0 ? false : _k, _l = props.track, track = _l === void 0 ? true : _l, _m = props.tooltipPlacement, tooltipPlacement = _m === void 0 ? 'top' : _m, tooltipVisible = props.tooltipVisible, tipFormatter = props.tipFormatter, marks = props.marks, onChange = props.onChange, onClick = props.onClick, onAfterChange = props.onAfterChange, className = props.className, customisedCls = props.prefixCls, otherProps = __rest(props, ["defaultValue", "min", "max", "direction", "dots", "step", "disabled", "track", "tooltipPlacement", "tooltipVisible", "tipFormatter", "marks", "onChange", "onClick", "onAfterChange", "className", "prefixCls"]);
    var configContext = useContext(ConfigContext);
    var prefixCls = getPrefixCls('slider', configContext.prefixCls, customisedCls);
    var cls = classNames(prefixCls, className, prefixCls + "_" + direction, (_a = {},
        _a[prefixCls + "-with-marks"] = marks,
        _a[prefixCls + "_disabled"] = disabled,
        _a));
    var _o = useState(('value' in props
        ? Array.isArray(props.value)
            ? props.value
            : [props.value]
        : Array.isArray(defaultValue)
            ? defaultValue
            : [defaultValue])), sliderValues = _o[0], setSliderValues = _o[1];
    var _p = useState(false), isHovering = _p[0], setHovering = _p[1];
    var railRef = useRef(null);
    var trackRef = useRef(null);
    var thumbIdx = useRef(0);
    var isDragging = useRef(false);
    var mouseStartPos = useRef(0);
    var trackStartPos = useRef(0);
    var currVal = useRef(0);
    var isVertical = direction === 'vertical';
    var railNode = railRef.current;
    var trackNode = trackRef.current;
    var getValueToPercent = function (value) {
        return ((value - min) * 100) / (max - min);
    };
    var calculateTrackStyle = function () {
        var trackStyle = { left: '0%', right: '100%' };
        if (sliderValues.length === 1) {
            trackStyle.right = 100 - getValueToPercent(sliderValues[0]) + "%";
        }
        else {
            var leftValue = sliderValues[0] > sliderValues[1] ? sliderValues[1] : sliderValues[0];
            var rightValue = sliderValues[0] > sliderValues[1] ? sliderValues[0] : sliderValues[1];
            trackStyle.left = getValueToPercent(leftValue) + "%";
            trackStyle.right = 100 - getValueToPercent(rightValue) + "%";
        }
        return trackStyle;
    };
    var getRangeValue = function (val) {
        if (sliderValues.length === 1) {
            return [val];
        }
        var values = sliderValues;
        var val1 = values[0];
        var val2 = values[1];
        if ((val1 < val2 && val1 > val) || (val1 > val2 && val1 < val)) {
            values[0] = val;
        }
        if ((val1 < val2 && val2 < val) || (val1 > val2 && val2 > val)) {
            values[1] = val;
        }
        if (val1 > val && val2 < val) {
            var half = val2 + (val1 - val2) / 2;
            if (half >= val) {
                values[1] = val;
            }
            if (half < val) {
                values[0] = val;
            }
        }
        if (val2 > val && val1 < val) {
            var half = val1 + (val2 - val1) / 2;
            if (half >= val) {
                values[0] = val;
            }
            if (half < val) {
                values[1] = val;
            }
        }
        return values;
    };
    var handleOnChange = function (value) {
        !('value' in props) && setSliderValues(__spreadArrays(value));
        onChange &&
            onChange(sliderValues.length === 1 ? sliderValues[0] : [sliderValues[0], sliderValues[1]]);
    };
    var getWidthToValue = function (width) {
        var numOfSteps = (max - min) / step;
        var percent = 0;
        if (railNode) {
            percent = (width / railNode[isVertical ? 'clientHeight' : 'clientWidth']) * 100;
        }
        if (percent <= 0) {
            percent = 0;
        }
        if (percent >= 100) {
            percent = 100;
        }
        var num = numOfSteps * (percent / 100) + 0.5;
        var val = Math.floor(num) * step + min;
        return isVertical ? 100 - val : val;
    };
    var sliderOnClick = function (e) {
        if (isDragging.current || disabled) {
            return;
        }
        if (railNode) {
            var markOffset = railNode.getBoundingClientRect();
            var value = getWidthToValue(e[isVertical ? 'clientY' : 'clientX'] - markOffset[isVertical ? 'y' : 'x']);
            handleOnChange(getRangeValue(value));
        }
        onClick && onClick(e);
    };
    var handleThumbOnDragging = function (e) {
        if (!isDragging.current) {
            return;
        }
        var sliderVal = getWidthToValue(e[isVertical ? 'clientY' : 'clientX'] - mouseStartPos.current + trackStartPos.current);
        var val = sliderValues;
        if (sliderVal !== currVal.current) {
            val[thumbIdx.current] = sliderVal;
            handleOnChange(val);
            currVal.current = sliderVal;
        }
    };
    var handleThumbOnDragEnd = function () {
        isDragging.current = false;
        window.removeEventListener('mousemove', handleThumbOnDragging);
        window.removeEventListener('mouseup', handleThumbOnDragEnd);
        onAfterChange &&
            onAfterChange(sliderValues.length === 1 ? sliderValues[0] : [sliderValues[0], sliderValues[1]]);
    };
    var handleThumbOnMouseDown = function (idx, e) {
        if (disabled) {
            return;
        }
        thumbIdx.current = idx;
        isDragging.current = true;
        mouseStartPos.current = e[isVertical ? 'clientY' : 'clientX'];
        if (trackNode) {
            trackStartPos.current = isVertical ? trackNode.offsetTop : trackNode.clientWidth;
            if (sliderValues.length > 1) {
                var trackOffset = trackNode[isVertical ? 'offsetTop' : 'offsetLeft'];
                trackStartPos.current =
                    (idx === 1 && sliderValues[1] > sliderValues[0]) ||
                        (idx !== 1 && sliderValues[0] > sliderValues[1])
                        ? isVertical
                            ? trackOffset
                            : trackStartPos.current + trackOffset
                        : isVertical
                            ? trackNode.clientHeight + trackOffset
                            : trackOffset;
            }
        }
        window.addEventListener('mousemove', handleThumbOnDragging, { capture: true });
        window.addEventListener('mouseup', handleThumbOnDragEnd, { capture: true });
    };
    var getSteps = function () {
        var numOfSteps = (max - min) / step;
        var stepWidth = (100 * step) / (max - min);
        var res = [0];
        for (var i = 1; i < numOfSteps; i += 1) {
            res.push(i * stepWidth);
        }
        res.push(100);
        return res;
    };
    var isDotActive = function (dotVal) {
        if (sliderValues.length === 1) {
            return dotVal < sliderValues[0];
        }
        else {
            var _a = sliderValues[0] < sliderValues[1]
                ? [sliderValues[0], sliderValues[1]]
                : [sliderValues[1], sliderValues[0]], left = _a[0], right = _a[1];
            return dotVal < right && dotVal > left;
        }
    };
    var handleThumbOnMouseEnter = function (idx) {
        thumbIdx.current = idx;
        setHovering(true);
    };
    var handleThumbOnMouseLeave = function () {
        setHovering(false);
    };
    var renderMark = function (mark) {
        if (marks && marks[mark] && marks[mark].label) {
            var _a = marks[mark], label = _a.label, style = _a.style;
            return React.createElement("div", { style: style }, label);
        }
        else if (marks && marks[mark]) {
            return marks[mark];
        }
        else {
            return mark;
        }
    };
    useEffect(function () {
        'value' in props && setSliderValues(sliderValues);
    }, [props, sliderValues]);
    var trackStyle = calculateTrackStyle();
    return (React.createElement("div", __assign({ ref: ref }, otherProps, { className: cls, onClick: sliderOnClick }),
        React.createElement("div", { ref: railRef, className: prefixCls + "__rail" }),
        React.createElement("div", { ref: trackRef, className: classNames(prefixCls + "__track", (_b = {},
                _b[prefixCls + "__track_invisible"] = !track,
                _b)), style: (_c = {},
                _c[isVertical ? 'bottom' : 'left'] = trackStyle.left,
                _c[isVertical ? 'top' : 'right'] = trackStyle.right,
                _c) }),
        sliderValues.map(function (value, idx) {
            var _a, _b;
            var percent = getValueToPercent(value);
            return (React.createElement("div", { key: idx, tabIndex: 0, role: "slider", "aria-valuemax": max, "aria-valuemin": min, "aria-valuenow": value, "aria-disabled": disabled, className: classNames(prefixCls + "__thumb-container", (_a = {},
                    _a[prefixCls + "__thumb-container_hovering"] = idx === thumbIdx.current && isHovering,
                    _a[prefixCls + "__thumb-container_dragging"] = idx === thumbIdx.current && isDragging.current,
                    _a)), style: (_b = {
                        zIndex: idx === thumbIdx.current && (isDragging.current || isHovering) ? 2 : 1,
                        transform: isVertical ? 'translate(-50%, 50%)' : 'translate(-50%, -50%)'
                    },
                    _b[isVertical ? 'bottom' : 'left'] = percent + "%",
                    _b), onMouseEnter: function () { return handleThumbOnMouseEnter(idx); }, onMouseLeave: handleThumbOnMouseLeave, onMouseDown: function (e) { return handleThumbOnMouseDown(idx, e); } },
                React.createElement(Tooltip, { trigger: "manual", visible: 'tooltipVisible' in props
                        ? tooltipVisible
                        : idx === thumbIdx.current && (isDragging.current || isHovering), usePortal: false, placement: tooltipPlacement, title: tipFormatter ? tipFormatter(value) : value },
                    React.createElement("div", { className: prefixCls + "__thumb" }))));
        }),
        dots && (React.createElement("div", { className: prefixCls + "__dots" }, getSteps().map(function (val, idx) {
            var _a, _b;
            var stepVal = idx * step + min;
            return (React.createElement("div", { key: idx, style: (_a = {},
                    _a[isVertical ? 'bottom' : 'left'] = val + "%",
                    _a), className: classNames(prefixCls + "__dot", (_b = {},
                    _b[prefixCls + "__dot_active"] = isDotActive(stepVal),
                    _b)) }));
        }))),
        marks && (React.createElement("div", { className: prefixCls + "__marks" }, Object.keys(marks).map(function (mark, idx) {
            var _a;
            var percent = getValueToPercent(parseFloat(mark));
            return (React.createElement("div", { key: idx, style: (_a = {},
                    _a[isVertical ? 'bottom' : 'left'] = percent + "%",
                    _a), className: prefixCls + "__mark" }, renderMark(mark)));
        })))));
});
Slider.displayName = 'Slider';
export default Slider;
//# sourceMappingURL=index.js.map