import { computed, ref, toRef, nextTick, watch, createVNode } from "vue";
import { useProxiedModel } from "../proxied-model/index.mjs";
import { usePointer } from "../pointer/index.mjs";
import { useDraggableSortableGroupItem } from "../draggable-sortable-group/index.mjs";
import { propsFactory, getUid, convertToUnit, getCurrentInstanceName } from "../../utils/dist/index.mjs";
const makeDraggableSortableProps = propsFactory({
  clone: Function,
  itemKey: {
    type: [String, Function],
    default: () => (v) => v
  },
  modelValue: {
    type: Array,
    default: () => []
  },
  put: {
    type: Boolean,
    default: true
  },
  group: String
}, "draggable-sortable");
function useDraggableSortable(props, name = getCurrentInstanceName()) {
  const model = useProxiedModel(props, "modelValue", props.modelValue);
  const modelEls = /* @__PURE__ */ new Map();
  const modelIndexes = computed(() => {
    const indexes = /* @__PURE__ */ new Map();
    model.value.forEach((value, index) => indexes.set(typeof props.itemKey === "function" ? props.itemKey(value, index) : value[props.itemKey], index));
    return indexes;
  });
  const ghostEl = ref();
  const ghostVNode = ref();
  const active = ref();
  const indexToKey = (index) => {
    for (const [key, i] of modelIndexes.value) {
      if (index === i)
        return key;
    }
    return void 0;
  };
  const keyToIndex = (key) => modelIndexes.value.get(key);
  const keyToValue = (key) => model.value[modelIndexes.value.get(key)];
  const {
    isPointerMoving,
    pointerDown,
    pointerUp,
    pointerDownEl,
    pointerCurrentPosition,
    pointerMovement,
    pointerEvents
  } = usePointer({
    pointerMovePreventDefault: true
  });
  const ghostBox = ref();
  const id = `draggable-sortable-group-item-${getUid()}`;
  const item = {
    findContains: (target) => {
      if (target) {
        for (const [key, el] of modelEls) {
          if (el === target || (el == null ? void 0 : el.contains(target))) {
            return {
              key,
              el
            };
          }
        }
      }
      return void 0;
    },
    put: toRef(props, "put"),
    group: toRef(props, "group"),
    clone: (key) => {
      var _a, _b;
      const value = keyToValue(key);
      return (_b = (_a = props.clone) == null ? void 0 : _a.call(props, value)) != null ? _b : value;
    },
    enter: async (key, value, from) => {
      const index = keyToIndex(key);
      model.value.splice(index, 0, value);
      await nextTick();
      const el = modelEls.get(indexToKey(index));
      const box = el.getBoundingClientRect();
      pointerDown(new MouseEvent("mousedown", {
        clientY: from.position.top - (from.box.top - box.top),
        clientX: from.position.left - (from.box.left - box.left),
        relatedTarget: el
      }));
    },
    leave: async (key) => {
      model.value.splice(keyToIndex(key), 1);
      if (key === active.value) {
        pointerUp(new MouseEvent("mouseup", {
          clientY: pointerCurrentPosition.value.top,
          clientX: pointerCurrentPosition.value.left
        }));
      }
    }
  };
  const group = useDraggableSortableGroupItem(id, item);
  watch(modelIndexes, () => modelEls.clear());
  watch(pointerDownEl, (targetEl) => {
    var _a;
    ghostBox.value = targetEl ? (_a = item.findContains(targetEl)) == null ? void 0 : _a.el.getBoundingClientRect() : void 0;
  });
  watch(isPointerMoving, (val) => {
    var _a;
    active.value = val ? (_a = item.findContains(pointerDownEl.value)) == null ? void 0 : _a.key : void 0;
  });
  watch(pointerCurrentPosition, (val) => {
    var _a;
    if (!val || !active.value)
      return;
    const targetEl = document.elementFromPoint(val.left, val.top) || void 0;
    const key = (_a = item.findContains(targetEl)) == null ? void 0 : _a.key;
    if (key && active.value !== key) {
      if (item.put.value) {
        const oldIndex = keyToIndex(active.value);
        const newIndex = keyToIndex(key);
        model.value.splice(newIndex, 0, model.value.splice(oldIndex, 1)[0]);
      }
    } else if (!key && item.group.value && targetEl && pointerDownEl.value) {
      group == null ? void 0 : group.trySwap({
        id,
        key: active.value,
        box: ghostEl.value.getBoundingClientRect(),
        position: val
      }, {
        el: targetEl
      });
    }
  });
  return {
    active,
    model,
    modelIndexes,
    modelEls,
    keyToIndex,
    indexToKey,
    keyToValue,
    pointerEvents,
    ghostVNode,
    genGhost: () => {
      var _a, _b, _c, _d;
      return createVNode("div", {
        "ref": ghostEl,
        "class": `${name}__ghost`,
        "style": {
          left: convertToUnit((_a = ghostBox.value) == null ? void 0 : _a.left),
          top: convertToUnit((_b = ghostBox.value) == null ? void 0 : _b.top),
          width: convertToUnit((_c = ghostBox.value) == null ? void 0 : _c.width),
          height: convertToUnit((_d = ghostBox.value) == null ? void 0 : _d.height),
          transform: pointerMovement.value ? `translate3d(${convertToUnit(pointerMovement.value.left)}, ${convertToUnit(pointerMovement.value.top)}, 0px)` : void 0
        }
      }, [ghostVNode.value]);
    }
  };
}
export {
  makeDraggableSortableProps,
  useDraggableSortable
};
//# sourceMappingURL=index.mjs.map
