import { BrowserWindow, ipcMain } from 'electron';
import url from 'url';
import fse from 'fs-extra';
import log from 'electron-log';
import {
  ElectronUpdateWindowOptions,
  DefaultElectronUpdateWindowOptions
} from '../models/electron-update-window-options';

import { Channel } from '../types/channel.type';
import { ElectronWebContentsChannel } from '@ucap-webmessenger/electron-core';

export class ElectronUpdateWindowService {
  private customOptions: ElectronUpdateWindowOptions;
  private browserWindow: BrowserWindow;
  private templateUrl: string;

  constructor(options: ElectronUpdateWindowOptions) {
    this.customOptions = {
      ...DefaultElectronUpdateWindowOptions
    };
    if (!!options) {
      this.customOptions = {
        ...this.customOptions,
        ...options
      };
    }
  }

  set options(options: ElectronUpdateWindowOptions) {
    if (!!options) {
      this.customOptions = {
        ...this.customOptions,
        ...options
      };
    }
  }

  get options(): ElectronUpdateWindowOptions {
    return this.customOptions;
  }

  set templatePath(templatePath: string) {
    if (!!templatePath) {
      this.customOptions.templatePath = templatePath;
      this.updateTemplatePath();
    }
  }

  get templatePath(): string {
    if (!this.templateUrl) {
      this.updateTemplatePath();
    }
    return this.templateUrl;
  }

  show(versionInfo: { installed: string; latest: string }) {
    this.browserWindow = new BrowserWindow(this.customOptions);
    this.browserWindow.loadURL(this.templatePath);

    this.browserWindow.on('closed', () => {
      this.browserWindow = null;
    });
    this.browserWindow.webContents.on(
      ElectronWebContentsChannel.DidFinishLoad,
      () => {
        if (process.env.NODE_ENV === 'development') {
          this.browserWindow.webContents.openDevTools();
        }
        if (!!this.customOptions.onReady) {
          this.customOptions.onReady();
        }

        this.browserWindow.webContents.send(
          Channel.browserWindowSetContents,
          versionInfo
        );
      }
    );

    ipcMain.on(Channel.acceptUpdate, this._acceptUpdateHandler.bind(this));
    ipcMain.on(Channel.denyUpdate, this._denyUpdateHandler.bind(this));
    ipcMain.on(Channel.cancelDownload, this._cancelDownloadHandler.bind(this));
  }

  setDownloadValue(value: number, total: number) {
    this.browserWindow.webContents.send(Channel.downloadProcess, value, total);
  }
  setDownloadComplete() {
    this.browserWindow.webContents.send(Channel.downloadComplete);
  }
  close() {
    if (!this.browserWindow || this.browserWindow.isDestroyed()) {
      return;
    }
    this.browserWindow.destroy();
  }

  _acceptUpdateHandler() {
    if (!!this.customOptions.onAcceptUpdate) {
      this.customOptions.onAcceptUpdate();
    }
  }
  _denyUpdateHandler() {
    if (!!this.customOptions.onDenyUpdate) {
      this.customOptions.onDenyUpdate();
    }
  }
  _cancelDownloadHandler() {
    if (!!this.customOptions.onCancelDownload) {
      this.customOptions.onCancelDownload();
    }
  }

  private updateTemplatePath() {
    try {
      fse.statSync(this.customOptions.templatePath).isFile();

      this.templateUrl = url.format({
        pathname: this.customOptions.templatePath,
        protocol: 'file:',
        slashes: true
      });
    } catch (e) {
      log.error(
        'electron-update-window: Could not find template ("' +
          this.customOptions.templatePath +
          '").'
      );
    }
  }
}
