import path from 'path';
import {app, ipcMain, WebContents, WebFrameMain} from 'electron';
import {pathToFileURL} from 'url';

/**
 * @returns true, when the application is starded in develpoment mode
 */
export function inDevelopment(): boolean {
  return process.env.NODE_ENV === 'development';
}

/**
 * Converts an error into a stringified object
 * @param error
 * @returns an indented JSON srting
 */
export function stringifyError(error: Error): string {
  const {message, stack} = error;

  return JSON.stringify(
    {
      message,
      stack,
    },
    null,
    2,
  );
}

/**
 * resolves the path of the preload script, based on in which state the application is starded
 * @returns the path to the preload script
 */
export function getPreloadPath(): string {
  const preloadScript = '/dist-electron/preload.cjs';
  return path.join(app.getAppPath(), inDevelopment() ? '.' : '..', preloadScript);
}

/**
 * resolves teh path of the build ui
 * @returns the path of the ui
 */
export function getUIPath(): string {
  return path.join(app.getAppPath(), '/dist-svelte/index.html');
}

/**
 * @todo
 * adapter for the ipc handle function
 * @param event
 * @param handler
 */
export function ipcMainHandle<Event extends keyof EventPayloadMapping>(
  event: Event,
  handler: () => EventPayloadMapping[Event],
): void {
  ipcMain.handle(event, (eventInstance) => {
    validateEventFrame(eventInstance.senderFrame);
    return handler();
  });
}

/**
 * @todo
 * adapter for the webContents send function
 * @param event
 * @param webContents
 * @param payload
 */
export function ipcWebContentsSend<Event extends keyof EventPayloadMapping>(
  event: Event,
  webContents: WebContents,
  payload: EventPayloadMapping[Event],
): void {
  webContents.send(event, payload);
}

/**
 * barebones event validation
 * @param frame
 * @throws when an event gets listend to which is not invoked by the mainframe
 */
export function validateEventFrame(frame: WebFrameMain | null) {
  if (inDevelopment() && frame && new URL(frame.url).host === 'localhost:5123') {
    return;
  }
  if (!frame || frame.url !== pathToFileURL(getUIPath()).toString()) {
    throw new Error('Malicious Event');
  }
}
