"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Slider = void 0;
const react_1 = __importStar(require("react"));
const inlines_1 = require("inlines");
const Text_1 = require("../Text");
const varsUtilities_1 = require("../../varsUtilities");
const hooks_1 = require("../../hooks");
const pretty_number_1 = require("@based/pretty-number");
const utils_1 = require("../../utils");
const StyledBgSlider = (0, inlines_1.styled)('div', {
    backgroundColor: (0, varsUtilities_1.color)('action', 'neutral', 'subtleNormal'),
    borderRadius: 4,
    height: 6,
    width: '100%',
    position: 'absolute',
    bottom: 0,
});
const StyledStepProgress = (0, inlines_1.styled)('div', {
    backgroundColor: (0, varsUtilities_1.color)('action', 'primary', 'normal'),
    height: 6,
    borderRadius: 4,
    width: '20%',
    position: 'absolute',
    bottom: 0,
});
const StyledThumb = (0, inlines_1.styled)('div', {
    width: 8,
    height: 8,
    borderRadius: '50%',
    backgroundColor: (0, varsUtilities_1.color)('content', 'inverted', 'primary'),
    border: `5px solid ${(0, varsUtilities_1.color)('action', 'primary', 'normal')} `,
    cursor: 'pointer',
    position: 'absolute',
    right: '-4px',
    bottom: '-2px',
    [utils_1.BpMobile]: {
        width: '14px',
        height: '14px',
        right: '-2px',
        bottom: '-4px',
    },
});
const StyledLabel = (0, inlines_1.styled)('div', {
    padding: '4px 8px',
    width: 'fit-content',
    borderRadius: '4px',
    overflow: 'inherit',
    border: 'none',
    position: 'absolute',
    boxShadow: 'none',
    backgroundColor: (0, varsUtilities_1.color)('background', 'inverted', 'strong'),
    transform: 'translateX(-50%)',
    bottom: 24,
    marginLeft: '-5px',
    '&::after': {
        content: `''`,
        bottom: '-4px',
        left: 0,
        right: 0,
        marginLeft: 'auto',
        marginRight: 'auto',
        borderRadius: '3px',
        width: '12px',
        height: '12px',
        backgroundColor: (0, varsUtilities_1.color)('background', 'inverted', 'strong'),
        transform: 'rotate(45deg)',
        position: 'absolute',
    },
});
const preventBehavior = (e) => {
    e.preventDefault();
};
const preventBodyScroll = () => {
    document.addEventListener('touchmove', preventBehavior, {
        passive: false,
    });
};
const getClosestIndex = (xPosArray, newPercentage) => {
    for (let i = 0; i < xPosArray.length; i++) {
        const val = xPosArray[i];
        const next = xPosArray[i + 1];
        if (newPercentage === val) {
            return i;
        }
        else if (newPercentage < next && newPercentage > val) {
            const valDiff = Math.abs(val - newPercentage);
            const nextDiff = Math.abs(next - newPercentage);
            if (valDiff <= nextDiff) {
                return i;
            }
            else {
                return i + 1;
            }
        }
    }
    return 0;
};
const Slider = ({ data: items, min = 0, max, value, onChange = () => null, color = 'primary', steps = 1, valueFormat, style, }) => {
    if (steps && max === undefined) {
        max = 10;
    }
    if (steps !== 1 && !items && max) {
        items = [];
        let counter = 0;
        for (let i = min; i <= max; i += steps) {
            items.push({ id: `blah${i}`, index: counter, title: i.toString() });
            counter++;
        }
    }
    const [containerWidth, setContainerWidth] = (0, react_1.useState)(0);
    //  const [leftContainerSide, setLeftContainerSide] = useState(0)
    const [isUpdating, setIsUpdating] = (0, react_1.useState)(false);
    const [index, setIndex] = (0, react_1.useState)(value || 0);
    const [percentageX, setPercentageX] = (0, react_1.useState)(0);
    const refRangeContainer = (0, react_1.useRef)(null);
    const refLeftPart = (0, react_1.useRef)(null);
    const refThumb = (0, react_1.useRef)(null);
    const windowSize = (0, hooks_1.useWindowResize)();
    // change on window resize
    (0, react_1.useEffect)(() => {
        setContainerWidth(refRangeContainer.current?.getBoundingClientRect().width || 0);
    }, [windowSize]);
    // split number of items
    const splitUpRange = items
        ? 100 / (items.length - 1)
        : max
            ? max - min
            : undefined;
    const xPosArray = [];
    if (items) {
        for (let i = 0; i < items.length; i++) {
            xPosArray.push(items[i].index * splitUpRange);
        }
    }
    // make percentages
    const percentage = containerWidth / 100;
    (0, react_1.useEffect)(() => {
        if (max) {
            if (value !== undefined && !isUpdating) {
                setPercentageX((value / max) * 100);
            }
        }
        else if (value !== undefined && !isUpdating) {
            setPercentageX(xPosArray[index]);
        }
    }, [isUpdating, value, max]);
    (0, react_1.useEffect)(() => {
        if (xPosArray.length) {
            setIndex(getClosestIndex(xPosArray, percentageX));
        }
    }, [xPosArray, percentageX]);
    const setValue = (newPercentage, snap) => {
        if (xPosArray.length) {
            if (snap && refLeftPart.current !== null) {
                refLeftPart.current.style.transition = 'width 0.4s ease';
                if (refThumb.current) {
                    refThumb.current.style.transition =
                        'transform 0.4s ease, opacity 0.2s';
                }
            }
            const index = getClosestIndex(xPosArray, newPercentage);
            setPercentageX(snap ? xPosArray[index] : newPercentage);
            if (value !== index) {
                onChange(index);
            }
        }
        else {
            setPercentageX(newPercentage);
            const newValue = max && (newPercentage * (max - min)) / 100 + min;
            if (value !== newValue && typeof newValue === 'number') {
                onChange(Math.trunc(newValue));
            }
        }
    };
    const moveHandler = (x) => {
        if (refRangeContainer.current !== null &&
            refThumb.current !== null &&
            refLeftPart.current !== null) {
            refRangeContainer.current.style.cursor = 'grabbing';
            refThumb.current.style.cursor = 'grabbing';
            refLeftPart.current.style.transition = 'width 0s';
            if (refThumb.current) {
                refThumb.current.style.transition = 'transform 0s, opacity 0.2s';
            }
            if (x > 0 && x < containerWidth) {
                refRangeContainer.current.style.cursor = 'pointer';
                setValue(Math.round(x / percentage));
            }
            if (x < 0) {
                setValue(0);
            }
            if (x > containerWidth) {
                setValue(100);
            }
        }
    };
    const mouseMoveHandler = (e) => {
        if (refRangeContainer.current !== null) {
            moveHandler(e.clientX - refRangeContainer.current.getBoundingClientRect().left);
        }
    };
    const mouseUpHandler = () => {
        if (refRangeContainer.current !== null && refThumb.current !== null) {
            refRangeContainer.current.style.cursor = 'pointer';
            refThumb.current.style.cursor = 'pointer';
            window.removeEventListener('mousemove', mouseMoveHandler);
            window.removeEventListener('mouseup', mouseUpHandler);
            setContainerWidth(refRangeContainer.current?.getBoundingClientRect().width || 0);
            setIsUpdating(false);
            // if (onEndSliding) {
            //   onEndSliding()
            // }
        }
    };
    const onMouseDownHandler = () => {
        setIsUpdating(true);
        if (refRangeContainer.current !== null) {
            refRangeContainer.current.style.cursor = 'grabbing';
        }
        // if (onStartSliding) {
        //   onStartSliding()
        // }
        window.addEventListener('mouseup', mouseUpHandler);
        window.addEventListener('mousemove', mouseMoveHandler);
    };
    const onTouchStart = () => {
        preventBodyScroll();
        setIsUpdating(true);
        // if (onStartSliding) {
        //   onStartSliding()
        // }
    };
    const onTouchEnd = (e) => {
        document.removeEventListener('touchmove', preventBehavior);
        setIsUpdating(false);
        // if (onEndSliding) {
        //   onEndSliding()
        // }
        onClickSnap(e);
    };
    // Touch functions
    const onTouchMoveHandler = (e) => {
        e.stopPropagation();
        if (refRangeContainer.current !== null) {
            moveHandler(e.touches[0].clientX -
                refRangeContainer.current?.getBoundingClientRect().left);
        }
    };
    const onClickSnap = (e) => {
        if (refRangeContainer.current) {
            const correctedMouseXPos = e.clientX - refRangeContainer.current?.getBoundingClientRect().left;
            if (correctedMouseXPos > 0 && correctedMouseXPos < containerWidth) {
                setValue(Math.round(correctedMouseXPos / percentage), true);
            }
        }
    };
    const keyDownHandler = (e) => {
        e.preventDefault();
        e.stopPropagation();
        const index = getClosestIndex(xPosArray, percentageX);
        if (e.key === 'ArrowRight' && percentageX !== 100) {
            setValue(xPosArray[index + 1]);
        }
        if (e.key === 'ArrowLeft') {
            setValue(xPosArray[index - 1]);
        }
    };
    return (react_1.default.createElement(inlines_1.styled.div, { style: { width: '100%', position: 'relative', minWidth: 340, ...style } },
        react_1.default.createElement(inlines_1.styled.div, { tabIndex: 0, onKeyDown: keyDownHandler, onMouseDown: onMouseDownHandler, onClick: onClickSnap, ref: refRangeContainer, onTouchStart: onTouchStart, onTouchMove: onTouchMoveHandler, onTouchEnd: onTouchEnd },
            react_1.default.createElement(StyledLabel, { style: { left: `${percentageX}%` } },
                react_1.default.createElement(Text_1.Text, { color: "inverted", selectable: "none", weight: "strong" }, items
                    ? valueFormat
                        ? (0, pretty_number_1.prettyNumber)(Number(items[index]?.title), valueFormat)
                        : items[index]?.title
                    : max
                        ? (percentageX * max) / 100
                        : '')),
            react_1.default.createElement(StyledBgSlider, null),
            react_1.default.createElement(StyledStepProgress, { ref: refLeftPart, style: {
                    width: `${percentageX}%`,
                    backgroundColor: (0, varsUtilities_1.color)('action', color, 'normal'),
                } },
                react_1.default.createElement(StyledThumb, { ref: refThumb, style: {
                        border: `5px solid ${(0, varsUtilities_1.color)('action', color, 'normal')} `,
                    } })))));
};
exports.Slider = Slider;
//# sourceMappingURL=index.js.map