import { contextBridge, ipcRenderer, IpcRendererEvent } from 'electron';
import { API_OBJ_NAME, PreloadApi } from '../common/preloadApi';
import { RendererApi } from '../common/rendererApi';
import { keys } from 'ts-transformer-keys';
import { MainApi } from '../common/mainApi';

let rapi: RendererApi = getNopRendererApi();
for (const name of keys<RendererApi>()) {
  register(name);
}

// Renderer API を Mainプロセスから呼び出せるように登録する
function register(name: string): void {
  // eslint-disable-next-line
  ipcRenderer.on(name, (evt: IpcRendererEvent, ...args: any[]) => {
    // eslint-disable-next-line
    (rapi as any)[name].apply(rapi, args);
  });
}

// 何もしない RendererApi を作成する
function getNopRendererApi(): RendererApi {
  const obj: any = {}; // eslint-disable-line
  const func = () => {}; // eslint-disable-line
  for (const n of keys<RendererApi>()) {
    obj[n] = func;
  }
  return obj;
}

function createMainApi(): MainApi {
  // eslint-disable-next-line
  function func(name: keyof MainApi): (...args: any[]) => Promise<any> {
    return (...args) => ipcRenderer.invoke(name, ...args);
  }
  const obj: any = {}; // eslint-disable-line
  for (const name of keys<MainApi>()) {
    obj[name] = func(name);
  }
  return obj;
}

const isWindows = process.platform == 'win32';
const sep = isWindows ? '\\' : '/';

contextBridge.exposeInMainWorld(API_OBJ_NAME, {
  main: createMainApi(),
  register: r => {
    rapi = r;
  },
  os: {
    platform: process.platform,
    isWindows: isWindows,
    separator: sep,
  },
} as PreloadApi);
