import { shell } from 'electron/common';
import { app, dialog, BrowserWindow, ipcMain, Menu } from 'electron/main';

import * as path from 'node:path';
import * as url from 'node:url';

let mainWindow: BrowserWindow | null = null;

// Quit when all windows are closed.
app.on('window-all-closed', () => {
  app.quit();
});

const isMac = process.platform === 'darwin';

app.whenReady().then(() => {
  const helpMenu: Electron.MenuItemConstructorOptions = {
    role: 'help',
    submenu: [
      {
        label: 'Learn More',
        click: async () => {
          await shell.openExternal('https://electronjs.org');
        }
      },
      {
        label: 'Documentation',
        click: async () => {
          const version = process.versions.electron;
          await shell.openExternal(`https://github.com/electron/electron/tree/v${version}/docs#readme`);
        }
      },
      {
        label: 'Community Discussions',
        click: async () => {
          await shell.openExternal('https://discord.gg/electronjs');
        }
      },
      {
        label: 'Search Issues',
        click: async () => {
          await shell.openExternal('https://github.com/electron/electron/issues');
        }
      }
    ]
  };

  const macAppMenu: Electron.MenuItemConstructorOptions = { role: 'appMenu' };
  const template: Electron.MenuItemConstructorOptions[] = [
    ...(isMac ? [macAppMenu] : []),
    { role: 'fileMenu' },
    { role: 'editMenu' },
    { role: 'viewMenu' },
    { role: 'windowMenu' },
    helpMenu
  ];

  Menu.setApplicationMenu(Menu.buildFromTemplate(template));
});

// Find the shortest path to the electron binary
const absoluteElectronPath = process.execPath;
const relativeElectronPath = path.relative(process.cwd(), absoluteElectronPath);
const electronPath = absoluteElectronPath.length < relativeElectronPath.length
  ? absoluteElectronPath
  : relativeElectronPath;

const indexPath = path.resolve(app.getAppPath(), 'index.html');

function isTrustedSender (webContents: Electron.WebContents) {
  if (webContents !== (mainWindow && mainWindow.webContents)) {
    return false;
  }

  try {
    return url.fileURLToPath(webContents.getURL()) === indexPath;
  } catch {
    return false;
  }
}

ipcMain.handle('bootstrap', (event) => {
  return isTrustedSender(event.sender) ? electronPath : null;
});

async function createWindow (backgroundColor?: string) {
  await app.whenReady();

  const options: Electron.BrowserWindowConstructorOptions = {
    width: 960,
    height: 620,
    autoHideMenuBar: true,
    backgroundColor,
    webPreferences: {
      preload: url.fileURLToPath(new URL('preload.js', import.meta.url)),
      contextIsolation: true,
      sandbox: true,
      nodeIntegration: false
    },
    useContentSize: true,
    show: false
  };

  if (process.platform === 'linux') {
    options.icon = url.fileURLToPath(new URL('icon.png', import.meta.url));
  }

  mainWindow = new BrowserWindow(options);
  mainWindow.on('ready-to-show', () => mainWindow!.show());

  mainWindow.webContents.setWindowOpenHandler(details => {
    shell.openExternal(details.url);
    return { action: 'deny' };
  });

  mainWindow.webContents.session.setPermissionRequestHandler((webContents, permission, done) => {
    const parsedUrl = new URL(webContents.getURL());

    const options: Electron.MessageBoxOptions = {
      title: 'Permission Request',
      message: `Allow '${parsedUrl.origin}' to access '${permission}'?`,
      buttons: ['OK', 'Cancel'],
      cancelId: 1
    };

    dialog.showMessageBox(mainWindow!, options).then(({ response }) => {
      done(response === 0);
    });
  });

  return mainWindow;
}

export const loadURL = async (appUrl: string) => {
  mainWindow = await createWindow();
  mainWindow.loadURL(appUrl);
  mainWindow.focus();
};

export const loadFile = async (appPath: string) => {
  mainWindow = await createWindow(appPath === 'index.html' ? '#2f3241' : undefined);
  mainWindow.loadFile(appPath);
  mainWindow.focus();
};
