import { reactive, ref, computed, watch } from 'vue';
import { useDraggable, UPDATE_MODEL_EVENT, DRAG_END_EVENT, DRAG_START_EVENT } from './useDraggable';

const dragInstanceMap = new WeakMap();
const updateStyle = (el, items) => {
  var _el$children;
  if (!(el !== null && el !== void 0 && (_el$children = el.children) !== null && _el$children !== void 0 && _el$children.length)) {
    return;
  }
  for (let index = 0; index < el.children.length; index++) {
    const node = el.children[index];
    const item = items[index];
    if (item !== null && item !== void 0 && item.draggable) {
      node.setAttribute('draggable', 'true');
    } else {
      node.removeAttribute('draggable');
    }
    const opacity = (item === null || item === void 0 ? void 0 : item.style.opacity) || (item === null || item === void 0 ? void 0 : item.elStyle.opacity) || '';
    const transition = (item === null || item === void 0 ? void 0 : item.style.transition) || (item === null || item === void 0 ? void 0 : item.elStyle.transition) || '';
    const transform = (item === null || item === void 0 ? void 0 : item.style.transform) || (item === null || item === void 0 ? void 0 : item.elStyle.transform) || '';
    const style = node.style;
    style.opacity = opacity;
    style.transition = transition;
    style.transform = transform;
  }
};
const init = (el, binding) => {
  if (binding.modifiers.disabled) {
    return;
  }
  const bindArg = binding.arg;
  const props = reactive({
    list: binding.value || [],
    droppable: binding.modifiers.droppable,
    disabled: binding.modifiers.disabled,
    isDirective: true,
    beforeDragend: bindArg === null || bindArg === void 0 ? void 0 : bindArg.beforeDragend
  });
  const containerRef = ref(el);
  const propsRef = computed(() => props);
  const emit = function (type) {
    var _bindArg$onDragstart, _bindArg$onDragend;
    for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
      args[_key - 1] = arguments[_key];
    }
    switch (type) {
      case DRAG_START_EVENT:
        bindArg === null || bindArg === void 0 || (_bindArg$onDragstart = bindArg.onDragstart) === null || _bindArg$onDragstart === void 0 || _bindArg$onDragstart.call(bindArg, ...args);
        break;
      case DRAG_END_EVENT:
        bindArg === null || bindArg === void 0 || (_bindArg$onDragend = bindArg.onDragend) === null || _bindArg$onDragend === void 0 || _bindArg$onDragend.call(bindArg, ...args);
        break;
      case UPDATE_MODEL_EVENT:
        const list = args[0] || [];
        list.forEach((item, index) => {
          propsRef.value.list[index] = list[index];
        });
        propsRef.value.list.length = list.length;
        break;
    }
  };
  const drag = useDraggable(containerRef, propsRef, {
    emit
  });
  el.addEventListener('mousedown', drag.onDragstart);
  el.addEventListener('dragover', drag.onDragover);
  el.addEventListener('drop', drag.onDragend);
  el.addEventListener('mouseup', drag.onDragend);
  el.addEventListener('dragend', drag.onDragend);
  el.addEventListener('transitionend', drag.onAnimationEnd);
  el.addEventListener('mousemove', drag.onMousemove);
  watch(() => drag.draggableItems, () => updateStyle(el, drag.draggableItems), {
    deep: true
  });
  dragInstanceMap.set(el, {
    drag,
    props
  });
};
var directive = {
  name: 'drag',
  mounted(el, binding) {
    init(el, binding);
  },
  updated(el, binding) {
    const {
      drag,
      props
    } = dragInstanceMap.get(el) || {};
    if (drag && props) {
      props.list = binding.value || [];
      props.droppable = binding.modifiers.droppable;
      props.disabled = binding.modifiers.disabled;
      drag.onUpdated();
      return;
    }
    init(el, binding);
  },
  beforeUnmount(el) {
    const {
      drag
    } = dragInstanceMap.get(el) || {};
    if (drag) {
      el.removeEventListener('mousedown', drag.onDragstart);
      el.removeEventListener('dragover', drag.onDragover);
      el.removeEventListener('drop', drag.onDragend);
      el.removeEventListener('mouseup', drag.onDragend);
      el.removeEventListener('dragend', drag.onDragend);
      el.removeEventListener('transitionend', drag.onAnimationEnd);
      el.removeEventListener('mousemove', drag.onMousemove);
      dragInstanceMap.delete(el);
    }
  }
};

export { directive as default };
