function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }

import React, { useContext, useMemo, useRef, useState } from 'react';
import cls from 'clsx';
import { addUnit, range, addNumber, preventDefault, getSizeStyle, stopPropagation } from '../utils';
import useTouch from '../hooks/use-touch';
import { getRect } from '../hooks/use-rect';
import useEventListener from '../hooks/use-event-listener';
import ConfigProviderContext from '../config-provider/ConfigProviderContext';

var Slider = function Slider(props) {
  var _useContext = useContext(ConfigProviderContext),
      prefixCls = _useContext.prefixCls,
      createNamespace = _useContext.createNamespace;

  var _createNamespace = createNamespace('slider', prefixCls),
      bem = _createNamespace[0];

  var _useState = useState(null),
      buttonRef1 = _useState[0],
      setButtonRef1 = _useState[1];

  var _useState2 = useState(null),
      buttonRef2 = _useState2[0],
      setButtonRef2 = _useState2[1];

  var buttonIndex = useRef();
  var startValue = useRef();
  var currentValue = useRef(props.value);
  var root = useRef();
  var dragStatus = useRef();
  var touch = useTouch(true);
  var scope = useMemo(function () {
    return Number(props.max) - Number(props.min);
  }, [props.max, props.min]);
  var wrapperStyle = useMemo(function () {
    var _extends2;

    var crossAxis = props.vertical ? 'width' : 'height';
    return _extends((_extends2 = {
      background: props.inactiveColor
    }, _extends2[crossAxis] = addUnit(props.barHeight), _extends2), props.style);
  }, [props.vertical, props.barHeight, props.inactiveColor, props.style]);

  var isRange = function isRange(val) {
    return props.range && Array.isArray(val);
  }; // 计算选中条的长度百分比


  var calcMainAxis = function calcMainAxis() {
    var value = props.value,
        min = props.min;

    if (isRange(value)) {
      return (value[1] - value[0]) * 100 / scope + "%";
    }

    return (+value - Number(min)) * 100 / scope + "%";
  }; // 计算选中条的开始位置的偏移量


  var calcOffset = function calcOffset() {
    var value = props.value,
        min = props.min;

    if (isRange(value)) {
      return (value[0] - Number(min)) * 100 / scope + "%";
    }

    return '0%';
  };

  var barStyle = useMemo(function () {
    var _style;

    var mainAxis = props.vertical ? 'height' : 'width';
    var style = (_style = {}, _style[mainAxis] = calcMainAxis(), _style.background = props.activeColor, _style);

    if (dragStatus.current) {
      style.transition = 'none';
    }

    var getPositionKey = function getPositionKey() {
      if (props.vertical) {
        return props.reverse ? 'bottom' : 'top';
      }

      return props.reverse ? 'right' : 'left';
    };

    style[getPositionKey()] = calcOffset();
    return style;
  }, [calcOffset]);

  var format = function format(value) {
    var min = +props.min;
    var max = +props.max;
    var step = +props.step;
    value = range(value, min, max);
    var diff = Math.round((value - min) / step) * step;
    return addNumber(min, diff);
  };

  var isSameValue = function isSameValue(newValue, oldValue) {
    return JSON.stringify(newValue) === JSON.stringify(oldValue);
  };

  var handleRangeValue = function handleRangeValue(value) {
    var _value$, _value$2;

    // 设置默认值
    var left = (_value$ = value[0]) != null ? _value$ : Number(props.min);
    var right = (_value$2 = value[1]) != null ? _value$2 : Number(props.max); // 处理两个滑块重叠之后的情况

    return left > right ? [right, left] : [left, right];
  };

  var updateValue = function updateValue(value, end) {
    if (isRange(value)) {
      value = handleRangeValue(value).map(format);
    } else {
      value = format(value);
    }

    if (!isSameValue(value, props.value)) {
      props.onChange == null ? void 0 : props.onChange(value);
    }

    if (end && !isSameValue(value, startValue.current)) {
      props.onChangeAfter == null ? void 0 : props.onChangeAfter(value);
    }

    return value;
  };

  var onClick = function onClick(event) {
    event.stopPropagation();

    if (props.disabled || props.readonly) {
      return;
    }

    var min = props.min,
        reverse = props.reverse,
        vertical = props.vertical,
        modelValue = props.value;
    var rect = getRect(root.current);

    var getDelta = function getDelta() {
      if (vertical) {
        if (reverse) {
          return rect.bottom - event.clientY;
        }

        return event.clientY - rect.top;
      }

      if (reverse) {
        return rect.right - event.clientX;
      }

      return event.clientX - rect.left;
    };

    var total = vertical ? rect.height : rect.width;
    var value = Number(min) + getDelta() / total * scope;

    if (isRange(modelValue)) {
      var left = modelValue[0],
          right = modelValue[1];
      var middle = (left + right) / 2;

      if (value <= middle) {
        updateValue([value, right], true);
      } else {
        updateValue([left, value], true);
      }
    } else {
      updateValue(value, true);
    }
  };

  var _onTouchStart = function onTouchStart(event) {
    if (props.disabled || props.readonly) {
      return;
    }

    touch.start(event);
    currentValue.current = JSON.parse(JSON.stringify(props.value));

    if (isRange(currentValue.current)) {
      startValue.current = currentValue.current.map(format);
    } else {
      startValue.current = format(currentValue.current);
    }

    dragStatus.current = 'start';
  };

  var onTouchMove = function onTouchMove(event) {
    if (props.disabled || props.readonly) {
      return;
    }

    if (dragStatus.current === 'start') {
      props.onDragStart == null ? void 0 : props.onDragStart(event, startValue.current);
    }

    preventDefault(event, true);
    touch.move(event);
    dragStatus.current = 'dragging';
    var rect = getRect(root.current);
    var delta = props.vertical ? touch.deltaY : touch.deltaX;
    var total = props.vertical ? rect.height : rect.width;
    var diff = delta / total * scope;

    if (props.reverse) {
      diff = -diff;
    }

    if (isRange(startValue.current)) {
      var index = props.reverse ? 1 - buttonIndex.current : buttonIndex.current;
      currentValue.current[index] = startValue.current[index] + diff;
    } else {
      currentValue.current = +startValue.current + diff;
    }

    updateValue(currentValue.current);
  };

  var onTouchEnd = function onTouchEnd(event) {
    if (props.disabled || props.readonly) {
      return;
    }

    if (dragStatus.current === 'dragging') {
      var value = updateValue(currentValue.current, true);
      props.onDragEnd == null ? void 0 : props.onDragEnd(event, value);
    }

    dragStatus.current = '';
  };

  var getButtonClassName = function getButtonClassName(index) {
    if (typeof index === 'number') {
      var position = ['left', 'right'];
      return bem('button-wrapper', position[index]);
    }

    return bem('button-wrapper', props.reverse ? 'left' : 'right');
  };

  var renderButtonContent = function renderButtonContent(value, index) {
    if (typeof index === 'number') {
      var slot = props[index === 0 ? 'leftButton' : 'rightButton'];

      if (slot) {
        return slot;
      }
    }

    if (typeof props.button === 'function') {
      return props.button({
        value: value
      });
    }

    if (props.button) {
      return props.button;
    }

    return /*#__PURE__*/React.createElement("div", {
      className: cls(bem('button')),
      style: getSizeStyle(props.buttonSize)
    });
  };

  var renderButton = function renderButton(buttounRef, index) {
    var value = typeof index === 'number' ? props.value[index] : props.value;
    return /*#__PURE__*/React.createElement("div", {
      ref: buttounRef,
      key: index,
      role: "slider",
      className: cls(getButtonClassName(index)),
      tabIndex: props.disabled || props.readonly ? -1 : 0,
      "aria-valuemin": props.min,
      "aria-valuenow": value,
      "aria-valuemax": props.max,
      "aria-orientation": props.vertical ? 'vertical' : 'horizontal',
      onTouchStart: function onTouchStart(event) {
        if (typeof index === 'number') {
          // save index of current button
          buttonIndex.current = index;
        }

        _onTouchStart(event);
      },
      onTouchEnd: onTouchEnd,
      onTouchCancel: onTouchEnd,
      onClick: stopPropagation
    }, renderButtonContent(currentValue.current, index));
  };

  useEventListener('touchmove', onTouchMove, {
    target: buttonRef1,
    depends: [touch.deltaX, touch.deltaY, props.disabled, props.readonly]
  });
  useEventListener('touchmove', onTouchMove, {
    target: buttonRef2,
    depends: [touch.deltaX, touch.deltaY, props.disabled, props.readonly]
  });
  return /*#__PURE__*/React.createElement("div", {
    ref: root,
    style: wrapperStyle,
    className: cls(props.className, bem({
      vertical: props.vertical,
      disabled: props.disabled
    })),
    onClick: onClick
  }, /*#__PURE__*/React.createElement("div", {
    className: cls(bem('bar')),
    style: barStyle
  }, props.range ? [renderButton(setButtonRef1, 0), renderButton(setButtonRef2, 1)] : renderButton(setButtonRef1)));
};

Slider.defaultProps = {
  min: 0,
  max: 100,
  step: 1
};
export default Slider;