"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 () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.Wheel = void 0;
const react_1 = __importStar(require("react"));
const TimePicker_styled_1 = require("./TimePicker.styled");
const utils_1 = require("./utils");
const PAGE_JUMP = 3;
const Wheel = ({ count, step, value, onChange, ariaLabel, autoFocus = false }) => {
    const viewportRef = (0, react_1.useRef)(null);
    const itemRef = (0, react_1.useRef)(null);
    const itemHeightRef = (0, react_1.useRef)(0);
    const scrollRafRef = (0, react_1.useRef)(null);
    const valueRef = (0, react_1.useRef)(value);
    valueRef.current = value;
    const items = Math.ceil(count / step);
    const lastValue = (items - 1) * step;
    const valueToIndex = (0, react_1.useCallback)((v) => {
        const idx = Math.round(v / step);
        if (idx < 0) {
            return 0;
        }
        if (idx >= items) {
            return items - 1;
        }
        return idx;
    }, [items, step]);
    const scrollToValue = (0, react_1.useCallback)((v, behavior) => {
        const vp = viewportRef.current;
        const h = itemHeightRef.current;
        if (!vp || h === 0) {
            return;
        }
        const idx = valueToIndex(v);
        vp.scrollTo({ top: idx * h, behavior });
    }, [valueToIndex]);
    (0, react_1.useLayoutEffect)(() => {
        const item = itemRef.current;
        if (!item) {
            return;
        }
        itemHeightRef.current = item.getBoundingClientRect().height;
        scrollToValue(valueRef.current, "auto");
    }, []);
    (0, react_1.useEffect)(() => {
        const item = itemRef.current;
        if (!item || typeof ResizeObserver === "undefined") {
            return;
        }
        const ro = new ResizeObserver((entries) => {
            const entry = entries[0];
            if (!entry) {
                return;
            }
            const h = entry.contentRect.height;
            if (h > 0 && h !== itemHeightRef.current) {
                itemHeightRef.current = h;
                scrollToValue(valueRef.current, "auto");
            }
        });
        ro.observe(item);
        return () => {
            ro.disconnect();
        };
    }, [scrollToValue]);
    (0, react_1.useEffect)(() => {
        const vp = viewportRef.current;
        const h = itemHeightRef.current;
        if (!vp || h === 0) {
            return;
        }
        const currentIdx = Math.round(vp.scrollTop / h);
        const desiredIdx = valueToIndex(value);
        if (currentIdx !== desiredIdx) {
            scrollToValue(value, "smooth");
        }
    }, [value, valueToIndex, scrollToValue]);
    const handleScroll = (0, react_1.useCallback)(() => {
        const vp = viewportRef.current;
        if (!vp) {
            return;
        }
        if (scrollRafRef.current != null) {
            cancelAnimationFrame(scrollRafRef.current);
        }
        scrollRafRef.current = requestAnimationFrame(() => {
            scrollRafRef.current = null;
            const vpInner = viewportRef.current;
            const h = itemHeightRef.current;
            if (!vpInner || h === 0) {
                return;
            }
            const rawIdx = Math.round(vpInner.scrollTop / h);
            const clamped = Math.max(0, Math.min(items - 1, rawIdx));
            const newValue = clamped * step;
            if (newValue !== valueRef.current) {
                onChange(newValue);
            }
        });
    }, [items, step, onChange]);
    const handleKeyDown = (0, react_1.useCallback)((e) => {
        let next;
        switch (e.key) {
            case "ArrowDown":
                next = valueRef.current + step;
                break;
            case "ArrowUp":
                next = valueRef.current - step;
                break;
            case "PageDown":
                next = valueRef.current + (step * PAGE_JUMP);
                break;
            case "PageUp":
                next = valueRef.current - (step * PAGE_JUMP);
                break;
            case "Home":
                next = 0;
                break;
            case "End":
                next = lastValue;
                break;
            default:
                return;
        }
        e.preventDefault();
        const clamped = Math.max(0, Math.min(lastValue, next));
        if (clamped !== valueRef.current) {
            onChange(clamped);
        }
    }, [step, lastValue, onChange]);
    (0, react_1.useEffect)(() => () => {
        if (scrollRafRef.current != null) {
            cancelAnimationFrame(scrollRafRef.current);
        }
    }, []);
    (0, react_1.useEffect)(() => {
        var _a;
        if (autoFocus) {
            (_a = viewportRef.current) === null || _a === void 0 ? void 0 : _a.focus({ preventScroll: true });
        }
    }, []);
    const itemElems = [];
    for (let i = 0; i < items; i++) {
        const v = i * step;
        itemElems.push(react_1.default.createElement(TimePicker_styled_1.StyledWheelItem, { key: i, ref: i === 0 ? itemRef : undefined }, (0, utils_1.padTwo)(v)));
    }
    return (react_1.default.createElement(TimePicker_styled_1.StyledWheelWrapper, null,
        react_1.default.createElement(TimePicker_styled_1.StyledWheelViewport, { ref: viewportRef, onScroll: handleScroll, onKeyDown: handleKeyDown, role: "spinbutton", "aria-label": ariaLabel, "aria-valuemin": 0, "aria-valuemax": lastValue, "aria-valuenow": value, "aria-valuetext": (0, utils_1.padTwo)(value), tabIndex: 0 },
            react_1.default.createElement(TimePicker_styled_1.StyledWheelPadder, null),
            itemElems,
            react_1.default.createElement(TimePicker_styled_1.StyledWheelPadder, null)),
        react_1.default.createElement(TimePicker_styled_1.StyledWheelFocusRing, { "aria-hidden": true })));
};
exports.Wheel = Wheel;
//# sourceMappingURL=Wheel.js.map