import { $$ } from './dom';
import { delegate } from './events';

let dragSrcEl: HTMLElement | null = null;

function dragStart(event: DragEvent, target: HTMLElement) {
  target.classList.add('dragging');
  dragSrcEl = target;

  if (!event.dataTransfer) return;

  if (event.dataTransfer.items.length === 0) {
    event.dataTransfer.setData('text/plain', '');
  }

  event.dataTransfer.effectAllowed = 'move';
}

function dragOver(event: DragEvent) {
  event.preventDefault();
  if (event.dataTransfer) {
    event.dataTransfer.dropEffect = 'move';
  }
}

function dragEnter(event: DragEvent, target: HTMLElement) {
  target.classList.add('over');
}

function dragLeave(event: DragEvent, target: HTMLElement) {
  target.classList.remove('over');
}

function drop(event: DragEvent, target: HTMLElement) {
  event.preventDefault();

  if (!dragSrcEl) return;

  dragSrcEl.classList.remove('dragging');

  if (dragSrcEl === target) return;

  // divide the target element into two sets of coordinates
  // and determine how to act based on the relative mouse position
  const bbox = target.getBoundingClientRect();
  const detX = bbox.left + bbox.width / 2;

  if (event.clientX < detX) {
    target.insertAdjacentElement('beforebegin', dragSrcEl);
  }
  else {
    target.insertAdjacentElement('afterend', dragSrcEl);
  }
}

function dragEnd(event: DragEvent, target: HTMLElement) {
  clearDragSource();

  if (target.parentNode) {
    $$('.over', target.parentNode).forEach(t => t.classList.remove('over'));
  }
}

export function initDraggables() {
  const draggableSelector = '.drag-container [draggable]';
  delegate(document, 'dragstart', { [draggableSelector]: dragStart});
  delegate(document, 'dragover', { [draggableSelector]: dragOver});
  delegate(document, 'dragenter', { [draggableSelector]: dragEnter});
  delegate(document, 'dragleave', { [draggableSelector]: dragLeave});
  delegate(document, 'dragend', { [draggableSelector]: dragEnd});
  delegate(document, 'drop', { [draggableSelector]: drop});
}

export function clearDragSource() {
  if (!dragSrcEl) return;

  dragSrcEl.classList.remove('dragging');
  dragSrcEl = null;
}