'use strict';

(() => {
  const DRAG_THRESHOLD = 4;
  let gesture = null;
  let syncQueued = false;

  function getCastleView(element) {
    return element?.closest?.('.castle-view') || null;
  }

  function isMovingBuilding(element) {
    const view = getCastleView(element);
    return Boolean(view?.querySelector('.castle-mode-banner')) || view?.classList.contains('castle-grid-placement-active');
  }

  function syncModeClasses() {
    syncQueued = false;
    document.querySelectorAll('.castle-view').forEach(view => {
      view.classList.toggle('is-moving-building', Boolean(view.querySelector('.castle-mode-banner')));
    });
  }

  function queueModeSync() {
    if (syncQueued) return;
    syncQueued = true;
    requestAnimationFrame(syncModeClasses);
  }

  function startPan(event) {
    if (event.button !== 0) return;
    const tile = event.target.closest?.('.castle-ground-tile');
    if (!tile || isMovingBuilding(tile)) return;
    const viewport = tile.closest('.castle-world-viewport');
    if (!viewport) return;

    gesture = {
      pointerId: event.pointerId,
      viewport,
      startX: event.clientX,
      startY: event.clientY,
      startScrollLeft: viewport.scrollLeft,
      startScrollTop: viewport.scrollTop,
      moved: false
    };

    event.preventDefault();
    viewport.classList.add('is-dragging', 'is-empty-space-panning');
    try { viewport.setPointerCapture?.(event.pointerId); } catch (_) {}
  }

  function movePan(event) {
    if (!gesture || event.pointerId !== gesture.pointerId) return;
    const dx = event.clientX - gesture.startX;
    const dy = event.clientY - gesture.startY;
    if (!gesture.moved && Math.hypot(dx, dy) >= DRAG_THRESHOLD) gesture.moved = true;
    gesture.viewport.scrollLeft = gesture.startScrollLeft - dx;
    gesture.viewport.scrollTop = gesture.startScrollTop - dy;
    event.preventDefault();
  }

  function stopPan(event) {
    if (!gesture || event.pointerId !== gesture.pointerId) return;
    const { viewport } = gesture;
    viewport.classList.remove('is-dragging', 'is-empty-space-panning');
    try { viewport.releasePointerCapture?.(event.pointerId); } catch (_) {}
    gesture = null;
  }

  function blockEmptyTileBuild(event) {
    const tile = event.target.closest?.('.castle-ground-tile');
    if (!tile || isMovingBuilding(tile)) return;
    event.preventDefault();
    event.stopImmediatePropagation();
  }

  document.addEventListener('pointerdown', startPan, true);
  document.addEventListener('pointermove', movePan, true);
  document.addEventListener('pointerup', stopPan, true);
  document.addEventListener('pointercancel', stopPan, true);
  document.addEventListener('click', blockEmptyTileBuild, true);

  const observer = new MutationObserver(queueModeSync);
  observer.observe(document.documentElement, { childList: true, subtree: true });
  queueModeSync();

  globalThis.ReinosCastleEmptySpaceNavigation = {
    VERSION: 1,
    syncModeClasses
  };
})();
