// Modular dockable panel system - handles drag, lock, snap-back, window-shade
// Feature Registration Pattern implementation

import type { ReaderContext } from "../core/reader-context";

let context: ReaderContext;

export function init(readerContext: ReaderContext): void {
  context = readerContext;
  const dockZones: DockZone[] = [
    { side: "left", x: 0, width: 400, height: window.innerHeight },
    {
      side: "right",
      x: window.innerWidth - 400,
      width: 400,
      height: window.innerHeight,
    },
  ];

  const state: PanelDockState = {
    panels: new Map(),
    dragState: null,
    dockZones,
  };

  context.events.on("panels:initialize", async () => {
    const settings = await loadSettings();
    for (const [panelId, panelState] of Object.entries(settings.panel_layout)) {
      state.panels.set(panelId, panelState as PanelState);
      createPanel(context, panelId, panelState as PanelState);
    }
    setupGlobalDragHandlers(context, state);
  });

  context.events.on("panel:toggle", (detail: { panelId: string }) => {
    const panelState = state.panels.get(detail.panelId);
    if (panelState) {
      panelState.visible = !panelState.visible;
      updatePanelVisibility(context, detail.panelId, panelState.visible);
    }
  });

  context.events.on("panel:collapse", (detail: { panelId: string }) => {
    const panelState = state.panels.get(detail.panelId);
    if (panelState) {
      panelState.collapsed = !panelState.collapsed;
      updatePanelCollapsed(context, detail.panelId, panelState.collapsed);
    }
  });

  context.events.on(
    "panel:move",
    (detail: { panelId: string; side: "left" | "right" }) => {
      movePanelToSide(context, state, detail.panelId, detail.side);
    },
  );
}

interface PanelDockState {
  panels: Map<string, PanelState>;
  dragState: DragState | null;
  dockZones: DockZone[];
}

interface DragState {
  panelId: string;
  startX: number;
  startY: number;
  currentX: number;
  currentY: number;
  isLocked: boolean;
}

interface DockZone {
  side: "left" | "right";
  x: number;
  width: number;
  height: number;
}

interface PanelState {
  side: "left" | "right";
  visible: boolean;
  collapsed: boolean;
  width_px: number;
  order: number;
  locked: boolean;
  last_valid_side: "left" | "right";
}

async function loadSettings(): Promise<any> {
  const response = await fetch("/readers/settings");
  if (!response.ok) return {};
  return await response.json();
}

function createPanel(
  context: ReaderContext,
  panelId: string,
  panelState: PanelState,
): void {
  const panel = document.createElement("div");
  panel.id = `panel-${panelId}`;
  panel.className = `reader-panel panel-${panelState.side}`;
  panel.dataset.panelId = panelId;
  panel.style.width = `${panelState.width_px}px`;

  if (!panelState.visible) {
    panel.classList.add("panel-hidden");
  }

  if (panelState.collapsed) {
    panel.classList.add("panel-collapsed");
  }

  context.elements.readerContent.appendChild(panel);
}

function updatePanelVisibility(
  context: ReaderContext,
  panelId: string,
  visible: boolean,
): void {
  const panel = document.getElementById(`panel-${panelId}`);
  if (panel) {
    panel.classList.toggle("panel-hidden", !visible);
  }
}

function updatePanelCollapsed(
  context: ReaderContext,
  panelId: string,
  collapsed: boolean,
): void {
  const panel = document.getElementById(`panel-${panelId}`);
  if (panel) {
    panel.classList.toggle("panel-collapsed", collapsed);
  }
}

function setupGlobalDragHandlers(
  context: ReaderContext,
  state: PanelDockState,
): void {
  document.addEventListener("mousedown", (e) => {
    const panelHeader = (e.target as HTMLElement).closest(".panel-header");
    if (panelHeader) {
      const panelId = (panelHeader as HTMLElement).dataset.panelId;
      if (panelId) {
        const panelState = state.panels.get(panelId);
        if (panelState && !panelState.locked) {
          state.dragState = {
            panelId,
            startX: e.clientX,
            startY: e.clientY,
            currentX: e.clientX,
            currentY: e.clientY,
            isLocked: false,
          };
        }
      }
    }
  });

  document.addEventListener("mousemove", (e) => {
    if (!state.dragState) return;
    state.dragState.currentX = e.clientX;
    state.dragState.currentY = e.clientY;
  });

  document.addEventListener("mouseup", () => {
    if (state.dragState) {
      const nearestZone = findNearestDockZone(
        state.dragState.currentX,
        state.dockZones,
      );
      if (nearestZone) {
        movePanelToSide(
          context,
          state,
          state.dragState.panelId,
          nearestZone.side,
        );
      }
      state.dragState = null;
    }
  });
}

function findNearestDockZone(x: number, zones: DockZone[]): DockZone | null {
  let nearest: DockZone | null = null;
  let minDistance = Infinity;

  for (const zone of zones) {
    const distance = Math.abs(x - (zone.x + zone.width / 2));
    if (distance < minDistance) {
      minDistance = distance;
      nearest = zone;
    }
  }

  return nearest;
}

function movePanelToSide(
  context: ReaderContext,
  state: PanelDockState,
  panelId: string,
  side: "left" | "right",
): void {
  const panelState = state.panels.get(panelId);
  if (!panelState) return;

  panelState.side = side;
  panelState.last_valid_side = side;

  const panel = document.getElementById(`panel-${panelId}`);
  if (panel) {
    panel.classList.remove("panel-left", "panel-right");
    panel.classList.add(`panel-${side}`);
  }

  context.events.emit("panel:moved", { panelId, side });
}
