const { app, BrowserWindow, systemPreferences } = require('electron');
const { autoUpdater } = require('electron-updater');
const contextMenu = require('electron-context-menu');
const path = require('path');
const fs = require('fs');

class ElectronApp {
  mainWindow = null;

  constructor(desktopApp) {
    this.desktop = desktopApp;
    this.log = desktopApp.log;
    this.log.info('start');

    contextMenu();

    // Spawn electron (ready invokes launch)
    app.on('window-all-closed', this.onAllClosed.bind(this));
    app.on('activate', this.onActivated.bind(this));
    app.on('ready', this.launch.bind(this));
  }

  onAllClosed = () => {
    if (process.platform !== 'darwin') {
      app.quit();
    }
  }

  onActivated = () => {
    if (this.mainWindow === null) {
      void this.launch();
    }
  }
  
  launch = async () => { 
    await systemPreferences.askForMediaAccess("camera");
    await this.spawnMainWindow();
    await this.updateApp();
    await this.desktop.dotnet.start();

    const url = `${this.desktop.urls.be}${this.desktop.paths.launch}`;
    this.log.info('[LAUNCH]', url);
    await this.mainWindow.loadURL(url);

    this.mainWindow.show();
  }
  
  spawnMainWindow = async () => {
    this.mainWindow = new BrowserWindow({
      width: 1000,
      height: 800,
      show: false,
      webPreferences: {
        // Set up the bride.js for inter-process communication.
        nodeIntegration: false, // is default value after Electron v5
        contextIsolation: true, // protect against prototype pollution
        enableRemoteModule: false, // turn off remote
        preload: path.join(__dirname, 'bridge.js'), // use a preload script
      }});
    this.mainWindow.maximize();
    // load some static HTML until the backend launches...
    const preloader = fs.readFileSync(path.join(__dirname, 'preloader.html'), 'utf-8');
    const encodedLoader = 'data:text/html;charset=UTF-8,' + encodeURIComponent(preloader);
    await this.mainWindow.loadURL(encodedLoader);

    this.mainWindow.on('preferred-size-changed', (s) => {
      this.log.info('size', s);
    });
    this.mainWindow.on('closed', () => this.mainWindow = null);
  }

  updateApp = async() => {
    if (this.desktop.appDev) return;
    this.log.info('[UPDATE]', 'check and notify...');
    try {
      await autoUpdater.checkForUpdatesAndNotify();
    } catch (e) {
      this.log.error('[UPDATE]', 'failed', e);
    }
  }
}

module.exports = ElectronApp;
