"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _vue = require("vue");
var _context = require("../context");
const REMOVE_DIST = 130;
function getPosition(e) {
  const obj = 'targetTouches' in e ? e.targetTouches[0] : e;
  return {
    pageX: obj.pageX,
    pageY: obj.pageY
  };
}
function useDrag(containerRef, direction, rawValues, min, max, formatValue, triggerChange, finishChange, offsetValues, editable, minCount) {
  const draggingValue = (0, _vue.ref)(null);
  const draggingIndex = (0, _vue.ref)(-1);
  const draggingDelete = (0, _vue.ref)(false);
  const cacheValues = (0, _vue.ref)(rawValues.value);
  const originValues = (0, _vue.ref)(rawValues.value);
  let mouseMoveEvent = null;
  let mouseUpEvent = null;
  let touchEventTarget = null;
  const {
    onDragChange,
    onDragStart
  } = (0, _context.useInjectUnstableSilder)();
  (0, _vue.watchEffect)(() => {
    if (draggingIndex.value === -1) {
      cacheValues.value = rawValues.value;
    }
  }, {
    flush: 'post'
  });
  (0, _vue.onUnmounted)(() => {
    document.removeEventListener('mousemove', mouseMoveEvent);
    document.removeEventListener('mouseup', mouseUpEvent);
    if (touchEventTarget) {
      touchEventTarget.removeEventListener('touchmove', mouseMoveEvent);
      touchEventTarget.removeEventListener('touchend', mouseUpEvent);
    }
  });
  const flushValues = (nextValues, nextValue, deleteMark) => {
    if (nextValue !== undefined) {
      draggingValue.value = nextValue;
    }
    cacheValues.value = nextValues;
    let changeValues = nextValues;
    if (deleteMark) {
      changeValues = nextValues.filter((_, i) => i !== draggingIndex.value);
    }
    triggerChange(changeValues);
    if (onDragChange) {
      onDragChange({
        rawValues: nextValues,
        deleteIndex: deleteMark ? draggingIndex.value : -1,
        draggingIndex: draggingIndex.value,
        draggingValue: nextValue
      });
    }
  };
  const updateCacheValue = (valueIndex, offsetPercent, deleteMark) => {
    if (valueIndex === -1) {
      // >>>> Dragging on the track
      const startValue = originValues.value[0];
      const endValue = originValues.value[originValues.value.length - 1];
      const maxStartOffset = min.value - startValue;
      const maxEndOffset = max.value - endValue;
      // Get valid offset
      let offset = offsetPercent * (max.value - min.value);
      offset = Math.max(offset, maxStartOffset);
      offset = Math.min(offset, maxEndOffset);
      // Use first value to revert back of valid offset (like steps marks)
      const formatStartValue = formatValue(startValue + offset);
      offset = formatStartValue - startValue;
      const cloneCacheValues = originValues.value.map(val => val + offset);
      flushValues(cloneCacheValues);
    } else {
      // >>>> Dragging on the handle
      const offsetDist = (max.value - min.value) * offsetPercent;
      // Always start with the valueIndex origin value
      const cloneValues = [...cacheValues.value];
      cloneValues[valueIndex] = originValues.value[valueIndex];
      const next = offsetValues(cloneValues, offsetDist, valueIndex, 'dist');
      flushValues(next.values, next.value, deleteMark);
    }
  };
  const onStartMove = (e, valueIndex, startValues) => {
    e.stopPropagation();
    // 如果是点击 track 触发的，需要传入变化后的初始值，而不能直接用 rawValues
    const initialValues = startValues || rawValues.value;
    const originValue = initialValues[valueIndex];
    draggingIndex.value = valueIndex;
    draggingValue.value = originValue;
    originValues.value = initialValues;
    cacheValues.value = initialValues;
    draggingDelete.value = false;
    const {
      pageX: startX,
      pageY: startY
    } = getPosition(e);
    // We declare it here since closure can't get outer latest value
    let deleteMark = false;
    // Internal trigger event
    if (onDragStart) {
      onDragStart({
        rawValues: initialValues,
        draggingIndex: valueIndex,
        draggingValue: originValue
      });
    }
    // Moving
    const onMouseMove = event => {
      event.preventDefault();
      const {
        pageX: moveX,
        pageY: moveY
      } = getPosition(event);
      const offsetX = moveX - startX;
      const offsetY = moveY - startY;
      const {
        width,
        height
      } = containerRef.value.getBoundingClientRect();
      let offSetPercent;
      let removeDist;
      switch (direction.value) {
        case 'btt':
          offSetPercent = -offsetY / height;
          removeDist = offsetX;
          break;
        case 'ttb':
          offSetPercent = offsetY / height;
          removeDist = offsetX;
          break;
        case 'rtl':
          offSetPercent = -offsetX / width;
          removeDist = offsetY;
          break;
        default:
          offSetPercent = offsetX / width;
          removeDist = offsetY;
      }
      // Check if need mark remove
      deleteMark = editable.value ? Math.abs(removeDist) > REMOVE_DIST && minCount.value < cacheValues.value.length : false;
      draggingDelete.value = deleteMark;
      updateCacheValue(valueIndex, offSetPercent, deleteMark);
    };
    // End
    const onMouseUp = event => {
      event.preventDefault();
      document.removeEventListener('mouseup', onMouseUp);
      document.removeEventListener('mousemove', onMouseMove);
      if (touchEventTarget) {
        touchEventTarget.removeEventListener('touchmove', mouseMoveEvent);
        touchEventTarget.removeEventListener('touchend', mouseUpEvent);
      }
      mouseMoveEvent = null;
      mouseUpEvent = null;
      touchEventTarget = null;
      finishChange(deleteMark);
      draggingIndex.value = -1;
      draggingDelete.value = false;
    };
    document.addEventListener('mouseup', onMouseUp);
    document.addEventListener('mousemove', onMouseMove);
    e.currentTarget.addEventListener('touchend', onMouseUp);
    e.currentTarget.addEventListener('touchmove', onMouseMove);
    mouseMoveEvent = onMouseMove;
    mouseUpEvent = onMouseUp;
    touchEventTarget = e.currentTarget;
  };
  // Only return cache value when it mapping with rawValues
  const returnValues = (0, _vue.computed)(() => {
    const sourceValues = [...rawValues.value].sort((a, b) => a - b);
    const targetValues = [...cacheValues.value].sort((a, b) => a - b);
    const counts = {};
    targetValues.forEach(val => {
      counts[val] = (counts[val] || 0) + 1;
    });
    sourceValues.forEach(val => {
      counts[val] = (counts[val] || 0) - 1;
    });
    const maxDiffCount = editable.value ? 1 : 0;
    const diffCount = Object.values(counts).reduce((prev, next) => prev + Math.abs(next), 0);
    return diffCount <= maxDiffCount ? cacheValues.value : rawValues.value;
  });
  return [draggingIndex, draggingValue, draggingDelete, returnValues, onStartMove];
}
var _default = exports.default = useDrag;