import { NileGrid } from "../nile-grid";

/** initHeadResize
 * @param el Target element
 * @param ev Pointer event
 * @param downXRef Reference to store downX value
 * @param startWRef Reference to store startW value
 * @returns Object containing target element and column index
 */
export function initHeadResize(
  el: HTMLElement,
  ev: PointerEvent,
  downXRef: { value: number },
  startWRef: { value: number }
) {
  ev.preventDefault();
  ev.stopPropagation();

  const cStart = Number(el.dataset.cStart);
  if (!cStart) return null;

  const span = Number(el.getAttribute('colspan')) || 1;
  const col = Math.max(0, cStart + span - 1 - 1);

  downXRef.value = ev.clientX;
  startWRef.value = el.getBoundingClientRect().width;

  const target = ev.currentTarget as HTMLElement;
  target.setPointerCapture(ev.pointerId);

  el.dispatchEvent(
    new CustomEvent('nile-column-resize', {
      detail: { col, widthPx: startWRef.value },
      bubbles: true,
      composed: true,
    })
  );

  el.dispatchEvent(
    new CustomEvent('nile-resize-start', { bubbles: true, composed: true })
  );

  return { target, col };
}

/** headResizeMove
 * @param el Target element
 * @param col Column index
 * @param startW Starting width
 * @param downX Down X coordinate
 * @param e Pointer event
 * @param nileGrid NileGrid instance
 * @returns void
 */
export function headResizeMove(
  el: HTMLElement,
  col: number,
  startW: number,
  downX: number,
  e: PointerEvent,
  nileGrid: NileGrid
) {
  const widthPx = Math.max(nileGrid.minColumnWidth, Math.round(startW + (e.clientX - downX)));
  el.dispatchEvent(
    new CustomEvent('nile-column-resize', {
      detail: { col, widthPx },
      bubbles: true,
      composed: true,
    })
  );
}

/** headResizeDone
 * @param el Target element
 * @param ev Pointer event
 * @param target Target element
 * @param move Pointer move handler
 * @returns void
 */
export function headResizeDone(
  el: HTMLElement,
  col: number,
  ev: PointerEvent,
  target: HTMLElement,
  move: (e: PointerEvent) => void
) {
  target.releasePointerCapture(ev.pointerId);
  target.removeEventListener('pointermove', move);

  el.dispatchEvent(
    new CustomEvent('nile-resize-end', { bubbles: true, composed: true, detail: { col: col } })
  );
}

/** addListeners
 * @param target Target element
 * @param move Pointer move handler
 * @param done Pointer up handler
 * @returns void
 */
export function addListeners(target: HTMLElement, move: (e: PointerEvent) => void, done: (e: PointerEvent) => void) {
  target.addEventListener('pointermove', move);
  target.addEventListener('pointerup', done);
  target.addEventListener('pointercancel', done);

  window.addEventListener('pointerup', done, { once: true });
}

/** removeListeners
 * @param target Target element
 * @param move Pointer move handler
 * @param done Pointer up handler
 * @returns void
 */
export function removeListeners(target: HTMLElement, move: (e: PointerEvent) => void, done: (e: PointerEvent) => void) {
  target.removeEventListener('pointermove', move);
  target.removeEventListener('pointerup', done);
  target.removeEventListener('pointercancel', done);

  window.removeEventListener('pointerup', done);
}