import { BrowserWindow, BrowserWindowConstructorOptions, LoadURLOptions } from 'electron';
import { promisify } from 'util';
import { ISessionHelper } from '../session/i-session-helper';
import { AppWindow } from './app-window';
import { IUrlAppWindow } from './i-url-app-window';
import { WindowClosedError } from './window-closed-error';

export abstract class UrlAppWindow extends AppWindow implements IUrlAppWindow {
  protected loadOptions: LoadURLOptions;

  protected constructor(
    sessionHelper: ISessionHelper,
    uri: string,
    options: BrowserWindowConstructorOptions = {},
    loadOptions: LoadURLOptions = {}
  ) {
    const securedOptions: BrowserWindowConstructorOptions = {
      ...options,
      ...{
        webPreferences: {
          enableRemoteModule: false,
          nodeIntegration: false,
          contextIsolation: true,
        },
      },
    };
    super(sessionHelper, uri, securedOptions);
    this.loadOptions = loadOptions;
  }

  public async loadUrlSafe(url: string, options?: LoadURLOptions): Promise<void> {
    if (!this._window) {
      throw new WindowClosedError();
    }
    const waitInterval = 1000;
    let failedLoad = true;
    do {
      await new Promise((resolve) => {
        if (!this._window) {
          throw new WindowClosedError();
        }
        this._window.webContents.once('did-navigate', (event, navigationUrl, httpResponseCode) => {
          failedLoad = HttpCode.BAD_REQUEST <= httpResponseCode;
          resolve();
        });
        void this._window.loadURL(url, options);
      });
      if (failedLoad) {
        await promisify(setTimeout)(waitInterval);
      }
    } while (failedLoad);
  }

  protected load(window: BrowserWindow): Promise<void> {
    return window.loadURL(this.uri, this.loadOptions);
  }
}
