import {remote, ipcRenderer} from 'electron';

import {Observable} from 'rxjs/Observable';
import {Subscription} from 'rxjs/Subscription';

import 'rxjs/add/observable/throw';
import 'rxjs/add/observable/fromEvent';

import 'rxjs/add/operator/do';
import 'rxjs/add/operator/publish';

const isBrowser = process.type === 'browser';

if (!isBrowser) {
  remote.require(require.resolve('./remote-event-browser'));
}

const d = require('debug')('remote-event');

/**
 * Safely subscribes to an event on a BrowserWindow or its WebContents. This
 * method avoids the "remote event listener" Electron issue.
 *
 * @param browserWindow  BrowserWindow   - the window to listen to
 * @param event  String  - The event to listen to
 * @param onWebContents  Boolean  - If true, the event is on the window's
 *                                  WebContents, not on the window itself.
 *
 * @returns Observable<Object>  - an Observable representing the event.
 *                                Unsubscribing from the Observable will
 *                                remove the event listener.
 */
export function fromRemoteWindow(browserWindowOrWebView, event, onWebContents=false) {
  if (isBrowser) {
    if (onWebContents) {
      let wc = ('webContents' in browserWindowOrWebView ? browserWindowOrWebView.webContents : browserWindowOrWebView.getWebContents());
      return Observable.fromEvent(wc, event, (...args) => args);
    } else {
      Observable.fromEvent(browserWindowOrWebView, event, (...args) => args);
    }
  }

  if (Object.getPrototypeOf(browserWindowOrWebView).constructor.name === 'webview' && !onWebContents) {
    throw new Error("WebViews can only be used with onWebContents=true");
  }

  let type = onWebContents ? 'webcontents' : 'window';
  let id;
  if (onWebContents) {
    id = ('webContents' in browserWindowOrWebView ? browserWindowOrWebView.webContents : browserWindowOrWebView.getWebContents()).id;
  } else {
    id = browserWindowOrWebView.id;
  }

  const key = `electron-remote-event-${type}-${id}-${event}-${remote.getCurrentWebContents().id}`;

  d(`Subscribing to event with key: ${key}`);
  let {error} = ipcRenderer.sendSync(
    'electron-remote-event-subscribe',
    {type, id, event, onWebContents});

  if (error) {
    d(`Failed with error: ${error}`);
    return Observable.throw(new Error(error));
  }

  let ret = Observable.create((subj) => {
    let disp = new Subscription();
    disp.add(
      Observable.fromEvent(ipcRenderer, key, (e,arg) => arg)
        .do(() => d(`Got event: ${key}`))
        .subscribe(subj));

    disp.add(new Subscription(() => {
      d(`Got event: ${key}`);
      ipcRenderer.send('electron-remote-event-unsubscribe', key);
    }));

    return disp;
  });

  return ret.publish().refCount();
}

@@ -1169,59 +1169,245 @@
 %7B%0A  
-if (isBrowser) %7B%0A    if (onWebContents) %7B%0A      let
+let ctorName = Object.getPrototypeOf(browserWindowOrWebView).constructor.name;%0A%0A  if (isBrowser) %7B%0A    if (onWebContents) %7B%0A      let wc;%0A      if (ctorName === 'WebContents') %7B%0A        wc = browserWindowOrWebView;%0A      %7D else %7B%0A       
  wc 
@@ -1530,16 +1530,24 @@
 nts());%0A
+      %7D%0A
       re
@@ -1709,73 +1709,47 @@
  %7D%0A%0A
+%0A
   if (
-Object.getPrototypeOf(browserWindowOrWebView).constru
+(ctorName === 'webview' %7C%7C 
 ctor
-.n
+N
 ame 
@@ -1753,24 +1753,29 @@
 me === '
-webview'
+WebContents')
  && !onW
@@ -1818,16 +1818,32 @@
 ebViews 
+and WebContents 
 can only
@@ -1967,24 +1967,115 @@
 Contents) %7B%0A
+    if (ctorName === 'WebContents') %7B%0A      id = browserWindowOrWebView.id;%0A    %7D else %7B%0A  
     id = ('w
@@ -2196,16 +2196,22 @@
 ()).id;%0A
+    %7D%0A
   %7D else

Allow WebContents to be used directly