import {type Event, clipboard} from "electron/common";
import type {WebContents} from "electron/main";
import type {
  ContextMenuParams,
  MenuItemConstructorOptions,
} from "electron/renderer";
import process from "node:process";

import {BrowserWindow, Menu} from "@electron/remote";

import * as t from "../../../common/translation-util.ts";

export const contextMenu = (
  webContents: WebContents,
  event: Event,
  properties: ContextMenuParams,
) => {
  const isText = properties.selectionText !== "";
  const isLink = properties.linkURL !== "";
  const linkUrl = isLink ? new URL(properties.linkURL) : undefined;

  const makeSuggestion = (suggestion: string) => ({
    label: suggestion,
    visible: true,
    async click() {
      await webContents.insertText(suggestion);
    },
  });

  let menuTemplate: MenuItemConstructorOptions[] = [
    {
      label: t.__("Add to Dictionary"),
      visible:
        properties.isEditable && isText && properties.misspelledWord.length > 0,
      click(_item) {
        webContents.session.addWordToSpellCheckerDictionary(
          properties.misspelledWord,
        );
      },
    },
    {
      type: "separator",
      visible:
        properties.isEditable && isText && properties.misspelledWord.length > 0,
    },
    {
      label: `${t.__("Look Up")} "${properties.selectionText}"`,
      visible: process.platform === "darwin" && isText,
      click(_item) {
        webContents.showDefinitionForSelection();
      },
    },
    {
      type: "separator",
      visible: process.platform === "darwin" && isText,
    },
    {
      label: t.__("Cut"),
      visible: isText,
      enabled: properties.isEditable,
      accelerator: "CommandOrControl+X",
      click(_item) {
        webContents.cut();
      },
    },
    {
      label: t.__("Copy"),
      accelerator: "CommandOrControl+C",
      enabled: properties.editFlags.canCopy,
      click(_item) {
        webContents.copy();
      },
    },
    {
      label: t.__("Paste"), // Bug: Paste replaces text
      accelerator: "CommandOrControl+V",
      enabled: properties.isEditable,
      click() {
        webContents.paste();
      },
    },
    {
      type: "separator",
    },
    {
      label:
        linkUrl?.protocol === "mailto:"
          ? t.__("Copy Email Address")
          : t.__("Copy Link"),
      visible: isLink,
      click(_item) {
        clipboard.write({
          bookmark: properties.linkText,
          text:
            linkUrl?.protocol === "mailto:"
              ? linkUrl.pathname
              : properties.linkURL,
        });
      },
    },
    {
      label: t.__("Copy Image"),
      visible: properties.mediaType === "image",
      click(_item) {
        webContents.copyImageAt(properties.x, properties.y);
      },
    },
    {
      label: t.__("Copy Image URL"),
      visible: properties.mediaType === "image",
      click(_item) {
        clipboard.write({
          bookmark: properties.srcURL,
          text: properties.srcURL,
        });
      },
    },
  ];

  if (properties.misspelledWord) {
    if (properties.dictionarySuggestions.length > 0) {
      const suggestions: MenuItemConstructorOptions[] =
        properties.dictionarySuggestions.map((suggestion: string) =>
          makeSuggestion(suggestion),
        );
      menuTemplate = [...suggestions, ...menuTemplate];
    } else {
      menuTemplate.unshift({
        label: t.__("No Suggestion Found"),
        enabled: false,
      });
    }
  }
  // Hide the invisible separators on Linux and Windows
  // Electron has a bug which ignores visible: false parameter for separator menu items. So we remove them here.
  // https://github.com/electron/electron/issues/5869
  // https://github.com/electron/electron/issues/6906

  const filteredMenuTemplate = menuTemplate.filter(
    (menuItem) => menuItem.visible ?? true,
  );
  const menu = Menu.buildFromTemplate(filteredMenuTemplate);
  menu.popup({
    window: BrowserWindow.fromWebContents(webContents) ?? undefined,
    frame: properties.frame ?? undefined,
    x: properties.x,
    y: properties.y,
    sourceType: properties.menuSourceType,
  });
};
