import { app } from 'electron';
import * as path from 'path';
import { createWindow, getMainWindow } from '../window/create-window';

const CUSTOM_PROTOCOL = 'toju';
const DEEP_LINK_PREFIX = `${CUSTOM_PROTOCOL}://`;
const DEV_SINGLE_INSTANCE_EXIT_CODE_ENV = 'METOYOU_SINGLE_INSTANCE_EXIT_CODE';
const DEV_RELOAD_EXISTING_ARG = '--metoyou-dev-reload-existing';

let pendingDeepLink: string | null = null;

function resolveDevSingleInstanceExitCode(): number | null {
  const rawValue = process.env[DEV_SINGLE_INSTANCE_EXIT_CODE_ENV];

  if (!rawValue) {
    return null;
  }

  const parsedValue = Number.parseInt(rawValue, 10);

  return Number.isInteger(parsedValue) && parsedValue > 0
    ? parsedValue
    : null;
}

function extractDeepLink(argv: string[]): string | null {
  return argv.find((argument) => typeof argument === 'string' && argument.startsWith(DEEP_LINK_PREFIX)) || null;
}

function focusMainWindow(): void {
  const mainWindow = getMainWindow();

  if (!mainWindow || mainWindow.isDestroyed()) {
    return;
  }

  if (mainWindow.isMinimized()) {
    mainWindow.restore();
  }

  mainWindow.show();
  mainWindow.focus();
}

function forwardDeepLink(url: string): void {
  const mainWindow = getMainWindow();

  if (!mainWindow || mainWindow.isDestroyed() || mainWindow.webContents.isLoadingMainFrame()) {
    pendingDeepLink = url;

    if (app.isReady() && (!mainWindow || mainWindow.isDestroyed())) {
      void createWindow();
    }

    return;
  }

  focusMainWindow();
  mainWindow.webContents.send('deep-link-received', url);
}

function registerProtocolClient(): void {
  if (process.defaultApp) {
    const appEntrypoint = process.argv[1];

    if (appEntrypoint) {
      app.setAsDefaultProtocolClient(CUSTOM_PROTOCOL, process.execPath, [path.resolve(appEntrypoint)]);
      return;
    }
  }

  app.setAsDefaultProtocolClient(CUSTOM_PROTOCOL);
}

export function initializeDeepLinkHandling(): boolean {
  const hasSingleInstanceLock = app.requestSingleInstanceLock();

  if (!hasSingleInstanceLock) {
    const devExitCode = resolveDevSingleInstanceExitCode();

    if (devExitCode != null) {
      app.exit(devExitCode);
    } else {
      app.quit();
    }

    return false;
  }

  registerProtocolClient();

  const initialDeepLink = extractDeepLink(process.argv);

  if (initialDeepLink) {
    pendingDeepLink = initialDeepLink;
  }

  app.on('second-instance', (_event, argv) => {
    if (resolveDevSingleInstanceExitCode() != null && argv.includes(DEV_RELOAD_EXISTING_ARG)) {
      app.relaunch();
      app.exit(0);
      return;
    }

    focusMainWindow();

    const deepLink = extractDeepLink(argv);

    if (deepLink) {
      forwardDeepLink(deepLink);
    }
  });

  app.on('open-url', (event, url) => {
    event.preventDefault();
    forwardDeepLink(url);
  });

  return true;
}

export function consumePendingDeepLink(): string | null {
  const deepLink = pendingDeepLink;

  pendingDeepLink = null;

  return deepLink;
}
