import { BrowserWindow } from "electron";
import { RuntimeOptionState, WindowGeometry } from "../../types";
import { updateOverlayWindowBoundsService } from "./overlay-window-service";

type OverlayLayer = "visible" | "invisible";

export interface OverlayManagerService {
  getMainWindow: () => BrowserWindow | null;
  setMainWindow: (window: BrowserWindow | null) => void;
  getInvisibleWindow: () => BrowserWindow | null;
  setInvisibleWindow: (window: BrowserWindow | null) => void;
  getOverlayWindow: (layer: OverlayLayer) => BrowserWindow | null;
  setOverlayWindowBounds: (layer: OverlayLayer, geometry: WindowGeometry) => void;
  getVisibleOverlayVisible: () => boolean;
  setVisibleOverlayVisible: (visible: boolean) => void;
  getInvisibleOverlayVisible: () => boolean;
  setInvisibleOverlayVisible: (visible: boolean) => void;
  getOverlayWindows: () => BrowserWindow[];
  broadcastToOverlayWindows: (channel: string, ...args: unknown[]) => void;
}

export function createOverlayManagerService(): OverlayManagerService {
  let mainWindow: BrowserWindow | null = null;
  let invisibleWindow: BrowserWindow | null = null;
  let visibleOverlayVisible = false;
  let invisibleOverlayVisible = false;

  return {
    getMainWindow: () => mainWindow,
    setMainWindow: (window) => {
      mainWindow = window;
    },
    getInvisibleWindow: () => invisibleWindow,
    setInvisibleWindow: (window) => {
      invisibleWindow = window;
    },
    getOverlayWindow: (layer) =>
      layer === "visible" ? mainWindow : invisibleWindow,
    setOverlayWindowBounds: (layer, geometry) => {
      updateOverlayWindowBoundsService(
        geometry,
        layer === "visible" ? mainWindow : invisibleWindow,
      );
    },
    getVisibleOverlayVisible: () => visibleOverlayVisible,
    setVisibleOverlayVisible: (visible) => {
      visibleOverlayVisible = visible;
    },
    getInvisibleOverlayVisible: () => invisibleOverlayVisible,
    setInvisibleOverlayVisible: (visible) => {
      invisibleOverlayVisible = visible;
    },
    getOverlayWindows: () => {
      const windows: BrowserWindow[] = [];
      if (mainWindow && !mainWindow.isDestroyed()) {
        windows.push(mainWindow);
      }
      if (invisibleWindow && !invisibleWindow.isDestroyed()) {
        windows.push(invisibleWindow);
      }
      return windows;
    },
    broadcastToOverlayWindows: (channel, ...args) => {
      const windows: BrowserWindow[] = [];
      if (mainWindow && !mainWindow.isDestroyed()) {
        windows.push(mainWindow);
      }
      if (invisibleWindow && !invisibleWindow.isDestroyed()) {
        windows.push(invisibleWindow);
      }
      for (const window of windows) {
        window.webContents.send(channel, ...args);
      }
    },
  };
}

export function broadcastRuntimeOptionsChangedRuntimeService(
  getRuntimeOptionsState: () => RuntimeOptionState[],
  broadcastToOverlayWindows: (channel: string, ...args: unknown[]) => void,
): void {
  broadcastToOverlayWindows("runtime-options:changed", getRuntimeOptionsState());
}

export function setOverlayDebugVisualizationEnabledRuntimeService(
  currentEnabled: boolean,
  nextEnabled: boolean,
  setState: (enabled: boolean) => void,
  broadcastToOverlayWindows: (channel: string, ...args: unknown[]) => void,
): boolean {
  if (currentEnabled === nextEnabled) return false;
  setState(nextEnabled);
  broadcastToOverlayWindows("overlay-debug-visualization:set", nextEnabled);
  return true;
}
