import { _ as _define_property } from "@swc/helpers/_/_define_property";
import { _ as _object_spread } from "@swc/helpers/_/_object_spread";
import { _ as _sliced_to_array } from "@swc/helpers/_/_sliced_to_array";
import React, { useEffect, useMemo, useRef, useState } from "react";
import { useDrag } from "@use-gesture/react";
import { useSpring } from "@react-spring/web";
import classNames from "classnames";
import Indicator from "../indicator";
import { getRefValue, useRefState } from "../../hooks/use-ref-state";
import { defaultEffect } from "./effects/default";
import { focusEffect, updateTransform, useList } from "./effects/focus";
var defaultProps = {
    direction: 'horizontal',
    indicator: false,
    loop: false,
    duration: 3000,
    autoPlay: false,
    defaultValue: 0,
    touchable: true,
    effect: undefined
};
export var Swiper = /*#__PURE__*/ React.forwardRef(function(props, ref) {
    var boundIndex = function boundIndex(current) {
        var min = 0;
        var max = count - 1;
        if (current === max && !loop && props.slideSize) {
            var slideSize = props.slideSize;
            var swiperSize = getSwiperSize();
            var ratio = (swiperSize - slideSize) / slideSize;
            return bound(current, min, max - ratio);
        }
        return current;
    };
    var classPrefix = 'nut-swiper';
    var _$_object_spread = _object_spread({}, defaultProps, props), children = _$_object_spread.children, direction = _$_object_spread.direction, indicator = _$_object_spread.indicator, loop = _$_object_spread.loop, effect = _$_object_spread.effect, autoPlay = _$_object_spread.autoPlay, touchable = _$_object_spread.touchable, defaultValue = _$_object_spread.defaultValue, duration = _$_object_spread.duration, style = _$_object_spread.style, className = _$_object_spread.className;
    var isVertical = direction === 'vertical';
    var count = useMemo(function() {
        var c = 0;
        React.Children.map(children, function(child, index) {
            c += 1;
        });
        return c;
    }, [
        children
    ]);
    var getSlideSize = function() {
        if (props.slideSize) return props.slideSize;
        if (stageRef.current) {
            if (isVertical) return stageRef.current.offsetHeight;
            return stageRef.current.offsetWidth;
        }
        return 0;
    };
    var getSwiperSize = function() {
        if (swiperRef.current) {
            if (isVertical) return swiperRef.current.offsetHeight;
            return swiperRef.current.offsetWidth;
        }
        return 0;
    };
    var bound = function(v, min, max) {
        if (min !== undefined) {
            v = Math.max(v, min);
        }
        if (max !== undefined) {
            v = Math.min(v, max);
        }
        return v;
    };
    var timeoutRef = useRef(null);
    var _useState = _sliced_to_array(useState(false), 2), dragging = _useState[0], setDragging = _useState[1];
    var _useRefState = _sliced_to_array(useRefState(defaultValue), 2), current = _useRefState[0], setCurrent = _useRefState[1];
    var stageRef = useRef(null);
    var swiperRef = useRef(null);
    var _useSpring = _sliced_to_array(useSpring(function() {
        return {
            x: !isVertical ? current.current * 100 * -1 : 0,
            y: isVertical ? current.current * 100 * -1 : 0,
            s: 0,
            reset: function() {},
            config: {
                tension: 200,
                friction: 30
            }
        };
    }), 2), springs = _useSpring[0], api = _useSpring[1];
    useEffect(function() {
        var _obj;
        api.start((_obj = {}, _define_property(_obj, isVertical ? 'y' : 'x', boundIndex(current.current) * -1 * 100), _define_property(_obj, "immediate", true), _obj));
    }, [
        swiperRef.current
    ]);
    var swiperDirection = useRef(1);
    var _useList = _sliced_to_array(useList(effect, count, current), 2), transforms = _useList[0], setTransforms = _useList[1];
    // 自动播放
    var runTimeSwiper = function() {
        var durationNumber = typeof duration === 'string' ? parseInt(duration) : duration;
        var d = typeof autoPlay === 'number' ? autoPlay : durationNumber;
        timeoutRef.current = window.setTimeout(function() {
            next();
            runTimeSwiper();
        }, d);
    };
    useEffect(function() {
        if (!autoPlay || dragging) return;
        runTimeSwiper();
        return function() {
            if (timeoutRef.current) window.clearTimeout(timeoutRef.current);
        };
    }, [
        autoPlay,
        duration,
        dragging,
        count
    ]);
    var to = function(index) {
        var immediate = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : false;
        var _props_onChange;
        var targetIndex = bound(index, 0, count - 1);
        if (loop) {
            var cycleIndex = index % count;
            targetIndex = cycleIndex < 0 ? cycleIndex + count : cycleIndex;
        }
        setCurrent(targetIndex);
        (_props_onChange = props.onChange) === null || _props_onChange === void 0 ? void 0 : _props_onChange.call(props, targetIndex);
        if (effect) {
            updateTransform(transforms, setTransforms, effect, targetIndex);
        }
        var _obj;
        api.start((_obj = {}, // 这里需要统一成百分比
        _define_property(_obj, isVertical ? 'y' : 'x', (loop ? -index : boundIndex(targetIndex) * -1) * 100), _define_property(_obj, "s", 0), _define_property(_obj, "immediate", immediate), _obj));
    };
    var getSpringsAxis = function() {
        return springs[isVertical ? 'y' : 'x'];
    };
    var next = function() {
        to(Math.round(-getSpringsAxis().get() / 100) + 1);
    };
    var prev = function() {
        to(Math.round(-getSpringsAxis().get() / 100) - 1);
    };
    React.useImperativeHandle(ref, function() {
        return {
            to: to,
            next: next,
            prev: prev
        };
    });
    var bind = useDrag(function(state) {
        var axis = Number(isVertical);
        var slideSize = getSlideSize();
        var offset = state.offset[axis];
        setDragging(!!state.dragging);
        var distance = state.distance[axis];
        swiperDirection.current = state.direction[axis];
        if (state.last) {
            // 计算位置
            var swipeDirection = state.direction[axis];
            var velocity = state.velocity[axis];
            var minIndex = Math.floor(offset / slideSize);
            var maxIndex = minIndex + 1;
            var index = Math.round((offset + velocity * 2000 * swipeDirection) / slideSize);
            to(bound(index, minIndex, maxIndex));
        } else {
            var _obj;
            // 实时移动，换算百分比
            api.start((_obj = {}, _define_property(_obj, isVertical ? 'y' : 'x', -(offset / slideSize * 100)), _define_property(_obj, "s", distance / slideSize), _define_property(_obj, "immediate", true), _obj));
        }
    }, {
        enabled: touchable,
        transform: function(param) {
            var _param = _sliced_to_array(param, 2), x = _param[0], y = _param[1];
            return [
                -x,
                -y
            ];
        },
        from: function() {
            // 由百分比转换到像素
            var slideSize = getSlideSize();
            var x = springs.x.get() / 100 * slideSize;
            var y = springs.y.get() / 100 * slideSize;
            return [
                -x,
                -y
            ];
        },
        triggerAllEvents: true,
        bounds: function() {
            if (loop) return {};
            var slideSize = getSlideSize();
            var swiperSize = getSwiperSize();
            if (isVertical) {
                return {
                    top: 0,
                    bottom: (count - 1) * slideSize
                };
            }
            return {
                left: 0,
                right: (count - 1) * slideSize
            };
        },
        preventDefault: true,
        rubberband: true,
        axis: isVertical ? 'y' : 'x',
        pointer: {
            touch: true
        }
    });
    var renderIndicator = function() {
        if (/*#__PURE__*/ React.isValidElement(indicator)) return indicator;
        if (!indicator) return null;
        var _obj;
        return /*#__PURE__*/ React.createElement("div", {
            className: classNames((_obj = {}, _define_property(_obj, "".concat(classPrefix, "-indicator"), true), _define_property(_obj, "".concat(classPrefix, "-indicator-vertical"), isVertical), _define_property(_obj, "".concat(classPrefix, "-indicator-horizontal"), !isVertical), _obj))
        }, /*#__PURE__*/ React.createElement(Indicator, {
            current: getRefValue(current),
            total: count,
            direction: direction
        }));
    };
    var renderEffect = function() {
        if (!effect) return defaultEffect({
            children: children,
            getSpringsAxis: getSpringsAxis,
            loop: loop,
            count: count,
            isVertical: isVertical
        });
        if (effect && effect.name === 'focus') {
            return focusEffect({
                children: children,
                springs: springs,
                loop: loop,
                count: count,
                isVertical: isVertical,
                effect: effect,
                current: current,
                swiperDirection: swiperDirection,
                dragging: dragging,
                transforms: transforms
            });
        }
    };
    var renderSlides = function() {
        return /*#__PURE__*/ React.createElement("div", {
            ref: stageRef,
            className: classNames('nut-swiper-inner', {
                'nut-swiper-inner-vertical': isVertical,
                'nut-swiper-inner-horizontal': !isVertical
            }),
            style: _object_spread({}, props.slideSize ? _define_property({}, isVertical ? 'height' : 'width', "".concat(props.slideSize, "px")) : {})
        }, renderEffect());
    };
    return /*#__PURE__*/ React.createElement("div", _object_spread({
        className: classNames('nut-swiper', className),
        style: style,
        ref: swiperRef
    }, bind()), renderSlides(), renderIndicator());
});
Swiper.displayName = 'NutSwiper';
