const {
  app,
  BrowserView,
  session,
  shell,
} = require('electron');
const path = require('path');

const appJson = require('../app.json');

const { getPreference } = require('./preferences');
const {
  getWorkspace,
  setWorkspace,
} = require('./workspaces');

const sendToAllWindows = require('./send-to-all-windows');

const views = {};

const badgeCounts = {};

const rememberLastPageVisited = getPreference('rememberLastPageVisited');

const extractDomain = (fullUrl) => {
  const matches = fullUrl.match(/^https?:\/\/([^/?#]+)(?:[/?#]|$)/i);
  const domain = matches && matches[1];
  return domain ? domain.replace('www.', '') : null;
};

const addView = (browserWindow, workspace) => {
  const view = new BrowserView({
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
      partition: `persist:${workspace.id}`,
      preload: path.join(__dirname, '..', 'preload', 'view.js'),
    },
  });

  if (workspace.active) {
    browserWindow.setBrowserView(view);

    const contentSize = browserWindow.getContentSize();
    view.setBounds({
      x: global.showSidebar ? 68 : 0,
      y: 0,
      width: global.showSidebar ? contentSize[0] - 68 : contentSize[0],
      height: contentSize[1],
    });
    view.setAutoResize({
      width: true,
      height: true,
    });
  }

  view.webContents.on('did-start-loading', () => {
    if (getWorkspace(workspace.id).active) {
      sendToAllWindows('update-did-fail-load', false);
      sendToAllWindows('update-is-loading', true);
    }
  });

  view.webContents.on('did-stop-loading', () => {
    if (getWorkspace(workspace.id).active) {
      sendToAllWindows('update-is-loading', false);
    }

    const currentUrl = view.webContents.getURL();
    setWorkspace(workspace.id, {
      lastUrl: currentUrl,
    });
  });

  // https://electronjs.org/docs/api/web-contents#event-did-fail-load
  view.webContents.on('did-fail-load', (e, errorCode, errorDesc, validateUrl, isMainFrame) => {
    if (isMainFrame && errorCode < 0 && errorCode !== -3) {
      if (getWorkspace(workspace.id).active) {
        sendToAllWindows('update-did-fail-load', true);
      }
    }
  });

  view.webContents.on('new-window', (e, nextUrl) => {
    e.preventDefault();

    // open external url in browser if domain doesn't match.
    const curDomain = extractDomain(appJson.url);
    const nextDomain = extractDomain(nextUrl);

    // open new window
    if (
      nextDomain === null
      || nextDomain === curDomain
      || nextDomain === 'accounts.google.com'
      || nextDomain === 'feedly.com'
      || nextUrl.indexOf('oauth') > -1 // Works with Google & Facebook.
    ) {
      view.webContents.loadURL(nextUrl);
      return;
    }

    shell.openExternal(nextUrl);
  });

  // Hide Electron from UA to improve compatibility
  // https://github.com/quanglam2807/webcatalog/issues/182
  let uaStr = view.webContents.getUserAgent();
  uaStr = uaStr.replace(` ${app.getName()}/${app.getVersion()}`, '');
  uaStr = uaStr.replace(` Electron/${process.versions.electron}`, '');
  view.webContents.setUserAgent(uaStr);

  // Unread count badge
  const unreadCountBadge = getPreference('unreadCountBadge');
  if (unreadCountBadge) {
    view.webContents.on('page-title-updated', (e, title) => {
      const itemCountRegex = /[([{](\d*?)[}\])]/;
      const match = itemCountRegex.exec(title);

      const incStr = match ? match[1] : '';
      const inc = parseInt(incStr, 10) || 0;
      badgeCounts[workspace.id] = inc;

      let count = 0;
      Object.values(badgeCounts).forEach((c) => {
        count += c;
      });

      app.setBadgeCount(count);
    });
  }

  view.webContents.loadURL((rememberLastPageVisited && workspace.lastUrl) || appJson.url);

  views[workspace.id] = view;
};

const getView = id => views[id];

const setActiveView = (browserWindow, id) => {
  const view = views[id];
  browserWindow.setBrowserView(view);

  const contentSize = browserWindow.getContentSize();
  view.setBounds({
    x: global.showSidebar ? 68 : 0,
    y: 0,
    width: global.showSidebar ? contentSize[0] - 68 : contentSize[0],
    height: contentSize[1],
  });
  view.setAutoResize({
    width: true,
    height: true,
  });

  sendToAllWindows('update-is-loading', view.webContents.isLoading());
};

const removeView = (id) => {
  const view = views[id];
  session.fromPartition(`persist:${id}`).clearStorageData();
  view.destroy();
};

module.exports = {
  addView,
  getView,
  setActiveView,
  removeView,
};

@@ -2214,94 +2214,8 @@
 %3E %7B%0A
-    e.preventDefault();%0A%0A    // open external url in browser if domain doesn't match.%0A
     
@@ -2330,16 +2330,59 @@
 w window
+ normally if domain is not defined (about:)
 %0A    if 
@@ -2382,23 +2382,16 @@
     if (
-%0A      
 nextDoma
@@ -2401,25 +2401,107 @@
 === null
+) %7B
 %0A      
-%7C%7C
+return;%0A    %7D%0A%0A    e.preventDefault();%0A%0A    // load in same window%0A    if (%0A     
  nextDom
@@ -2739,24 +2739,85 @@
 urn;%0A    %7D%0A%0A
+    // open external url in browser if domain doesn't match.%0A
     shell.op

Fix Facebook Messenger calling features don't work correctly (#187)