import _Object$keys from 'babel-runtime/core-js/object/keys';
import _Object$create from 'babel-runtime/core-js/object/create';
import _typeof from 'babel-runtime/helpers/typeof';
import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
import _inherits from 'babel-runtime/helpers/inherits';
import { Subject } from 'rxjs/Subject';
import $$observable from 'symbol-observable';
import { Observable } from 'rxjs/Observable';
import { AsyncSubject } from 'rxjs/AsyncSubject';
import * as Scheduler from 'rxjs/scheduler/async';
import { ReplaySubject } from 'rxjs/ReplaySubject';
import { Model } from '@graphistry/falcor-model-rxjs';
import { PostMessageDataSource } from '@graphistry/falcor-socket-datasource';
import { $ref, $atom, $value, $invalidate } from '@graphistry/falcor-json-graph';
import fetchDataUntilSettled from '@graphistry/falcor-react-redux/lib/utils/fetchDataUntilSettled';

/**
 * @class Graphistry
 * @classdesc This object wraps a HTML IFrame of a Graphistry Visualization in order
 * to provide an API for interacting with the graph.
 * @extends Observable
 */

var Graphistry = function (_Observable) {
    _inherits(Graphistry, _Observable);

    /**
     * Create Graphistry Observable by extending observable's methods
     * @param {Object} source - The source observable.
     */
    function Graphistry(source) {
        _classCallCheck(this, Graphistry);

        if (!source || typeof source === 'function' || (typeof source === 'undefined' ? 'undefined' : _typeof(source)) !== 'object') {
            var _this = _possibleConstructorReturn(this, _Observable.call(this, source));
        } else {
            var _this = _possibleConstructorReturn(this, _Observable.call(this));

            if (typeof source[$$observable] === 'function') {
                _this.source = source[$$observable]();
            } else {
                _this.source = _this.constructor.from(source);
            }
        }
        return _possibleConstructorReturn(_this);
    }

    /**
     * Creates a new Observable with this as the source, and the passed
     * operator as the new Observable's operator.
     * @method Graphistry~lift
     * @param {Operator} operator - the operator defining the operation to take on the
     * observable
     * @return {Observable} a new observable with the operator applied
     */


    Graphistry.prototype.lift = function lift(operator) {
        var observable = new Graphistry(this);
        observable.operator = operator;
        return observable;
    };

    /**
     * Add columns to the current graph visuzliation's dataset
     * @method Graphistry.addColumns
     * @params {...Arrays} columns - One of more columns to be appended to the dataset
     * @return {Promise} A promise to return the result of the callback
     * @example
     * GraphistryJS(document.getElementById('viz'))
     *     .flatMap(function(g) {
     *         window.g = g;
     *         const columns = [
     *             ['edge', 'highways', [66, 101, 280], 'number'],
     *             ['point', 'theme parks', ['six flags', 'disney world', 'great america'], 'string']
     *         ];
     *         console.log('adding columns', columns);
     *         return g.addColumns.apply(g, columns);
     *     })
     *     .subscribe();
     */


    Graphistry.addColumns = function addColumns() {
        for (var _len = arguments.length, columns = Array(_len), _key = 0; _key < _len; _key++) {
            columns[_key] = arguments[_key];
        }

        var view = this.view;

        return new this(this.from(columns).concatMap(function (column) {
            return view.call('columns.add', column);
        }).takeLast(1).mergeMap(function () {
            return fetchDataUntilSettled({
                falcor: view, fragment: function fragment() {
                    var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
                        _ref$columns = _ref.columns,
                        columns = _ref$columns === undefined ? [] : _ref$columns;

                    return '{\n                    columns: {\n                        length, [0...' + (columns.length || 0) + ']: {\n                            name, dataType, identifier, componentType\n                        }\n                    }\n                }';
                }
            });
        }).takeLast(1).map(function (_ref2) {
            var data = _ref2.data;
            return data.toJSON();
        }).toPromise());
    };

    /**
    * Change colors based on an attribute
    * @method Graphistry.encodeColor
    * @param {GraphType} [graphType] - 'point' or 'edge'
    * @param {Attribute} [attribute] - name of data column, e.g., 'degree'
    * @param {Variant} [variation] - If there are more bins than colors, use 'categorical' to repeat colors and 'continuous' to interpolate
    * @param {Array} [colors] - array of color name or hex codes
    * @return {Promise} The result of the callback
    * @example
    *  GraphistryJS(document.getElementById('viz'))
    *     .flatMap(function (g) {
    *         window.g = g;
    *         return g.encodeColor('point', 'degree', 'categorical', ['black', 'white'])
    *     })
    *     .subscribe();
    */


    Graphistry.encodeColor = function encodeColor(graphType, attribute, variation, colors) {
        var view = this.view;

        return new this(view.set($value('histograms.encodings.' + graphType + '.color', { reset: false, variation: variation, name: 'user_' + Math.random(),
            encodingType: 'color', colors: colors, graphType: graphType, attribute: attribute })).map(function (_ref3) {
            var json = _ref3.json;
            return json.toJSON();
        }).toPromise());
    };

    /**
    * Reset color to value at page load
    * @method Graphistry.resetColor
    * @param {GraphType} [graphType] - 'point' or 'edge'
    * @return {Promise} The result of the callback
    * @example
    *  GraphistryJS(document.getElementById('viz'))
    *     .flatMap(function (g) {
    *         window.g = g;
    *         return g.encodeColor('point', 'degree', 'categorical', ['black', 'white'])
    *         return g.resetColor('point')
    *     })
    *     .subscribe();
    */


    Graphistry.resetColor = function resetColor(graphType) {
        var view = this.view;

        return new this(view.set($value('histograms.encodings.' + graphType + '.color', { reset: true, encodingType: 'color' })).map(function (_ref4) {
            var json = _ref4.json;
            return json.toJSON();
        }).toPromise());
    };

    //=========


    /**
    * Change icons based on an attribute
    * @method Graphistry.encodeIcons
    * @param {GraphType} [graphType] - 'point' or 'edge'
    * @param {Attribute} [attribute] - name of data column, e.g., 'icon'
    * @return {Promise} The result of the callback
    * @example
    *  GraphistryJS(document.getElementById('viz'))
    *     .flatMap(function (g) {
    *         window.g = g;
    *         return g.encodeIcons('point', 'icon')
    *     })
    *     .subscribe();
    */


    Graphistry.encodeIcons = function encodeIcons(graphType, attribute) {
        var view = this.view;

        return new this(view.set($value('histograms.encodings.' + graphType + '.icon', { reset: false, name: 'user_' + Math.random(),
            encodingType: 'icon', graphType: graphType, attribute: attribute })).map(function (_ref5) {
            var json = _ref5.json;
            return json.toJSON();
        }).toPromise());
    };

    /**
    * Reset icons to value at page load
    * @method Graphistry.resetIcons
    * @param {GraphType} [graphType] - 'point' or 'edge'
    * @return {Promise} The result of the callback
    * @example
    *  GraphistryJS(document.getElementById('viz'))
    *     .flatMap(function (g) {
    *         window.g = g;
    *         return g.encodeIcons('point', 'icon')
    *         return g.resetIcons('point')
    *     })
    *     .subscribe();
    */


    Graphistry.resetIcons = function resetIcons(graphType) {
        var view = this.view;

        return new this(view.set($value('histograms.encodings.' + graphType + '.icon', { reset: true, encodingType: 'icon' })).map(function (_ref6) {
            var json = _ref6.json;
            return json.toJSON();
        }).toPromise());
    };

    //=========


    /**
     * Change size based on an attribute
     * @method Graphistry.encodeSize
     * @param {GraphType} [graphType] - 'point'
     * @param {Attribute} [attribute] - name of data column, e.g., 'degree'
     * @return {Promise} The result of the callback
     * @example
     *  GraphistryJS(document.getElementById('viz'))
     *     .flatMap(function (g) {
     *         window.g = g;
     *         return g.encodeSize('point', 'community_infomap')
     *     })
     *     .subscribe();
     */


    Graphistry.encodeSize = function encodeSize(graphType, attribute) {
        var view = this.view;

        return new this(view.set($value('histograms.encodings.' + graphType + '.size', { reset: false, name: 'user_' + Math.random(),
            encodingType: 'size', graphType: graphType, attribute: attribute })).map(function (_ref7) {
            var json = _ref7.json;
            return json.toJSON();
        }).toPromise());
    };

    /**
     * Reset size to value at page load
     * @method Graphistry.resetSize
     * @param {GraphType} [graphType] - 'point'
     * @return {Promise} The result of the callback
     * @example
     *  GraphistryJS(document.getElementById('viz'))
     *     .flatMap(function (g) {
     *         window.g = g;
     *         return g.encodeSize('point', 'community_infomap')
     *         return g.resetSize('point')
     *     })
     *     .subscribe();
     */


    Graphistry.resetSize = function resetSize(graphType) {
        var view = this.view;

        return new this(view.set($value('histograms.encodings.' + graphType + '.size', { reset: true, encodingType: 'size' })).map(function (_ref8) {
            var json = _ref8.json;
            return json.toJSON();
        }).toPromise());
    };

    /**
    * Toggle a leftside panel
    * @method Graphistry.toggleLeftPanel
    * @param {string} [panel] - Name of panel: filters, exclusions, scene, labels, layout
    * @param {boolean} [turnOn] - Whether to make panel visible, or turn all off
    * @return {Promise} The result of the callback
    * @example
    *  GraphistryJS(document.getElementById('viz'))
    *     .flatMap(function (g) {
    *         window.g = g;
    *         console.log('opening filters');
    *         return g.toggleLeftPanel('filters', true);
    *     })
    *     .subscribe();
    */


    Graphistry.toggleLeftPanel = function toggleLeftPanel(panel, turnOn) {
        var view = this.view;

        if (turnOn) {
            return new this(view.set($value('filters.controls[0].selected', panel === 'filters'), $value('scene.controls[1].selected', panel === 'scene'), $value('labels.controls[0].selected', panel === 'labels'), $value('layout.controls[0].selected', panel === 'layout'), $value('exclusions.controls[0].selected', panel === 'exclusions'), $value('panels.left', panel === 'filters' ? $ref(view._path.concat('filters')) : panel === 'scene' ? $ref(view._path.concat('scene')) : panel === 'labels' ? $ref(view._path.concat('labels')) : panel === 'layout' ? $ref(view._path.concat('layout')) : $ref(view._path.concat('exclusions')))).map(function (_ref9) {
                var json = _ref9.json;
                return json.toJSON();
            }).toPromise());
        } else {
            return new this(view.set($value('panels.left', undefined), $value('filters.controls[0].selected', false), $value('scene.controls[1].selected', false), $value('labels.controls[0].selected', false), $value('layout.controls[0].selected', false), $value('exclusions.controls[0].selected', false)).map(function (_ref10) {
                var json = _ref10.json;
                return json.toJSON();
            }).toPromise());
        }
    };

    /**
     * Toggle inspector panel
     * @method Graphistry.toggleInspector
     * @param {boolean} [turnOn] - Whether to make panel visible
     * @return {Promise} The result of the callback
     * @example
     *  GraphistryJS(document.getElementById('viz'))
     *     .flatMap(function (g) {
     *         window.g = g;
     *         console.log('opening inspector panel');
     *         return g.toggleInspector(true);
     *     })
     *     .subscribe();
     */


    Graphistry.toggleInspector = function toggleInspector(turnOn) {
        var view = this.view;

        if (!turnOn) {
            return new this(view.set($value('panels.bottom', undefined), $value('inspector.controls[0].selected', false)).map(function (_ref11) {
                var json = _ref11.json;
                return json.toJSON();
            }).toPromise());
        } else {
            return new this(view.set($value('inspector.controls[0].selected', true), $value('timebar.controls[0].selected', false), $value('panels.bottom', $ref(view._path.concat('inspector')))).map(function (_ref12) {
                var json = _ref12.json;
                return json.toJSON();
            }).toPromise());
        }
    };

    /**
     * Toggle histogram panel
     * @method Graphistry.toggleHistograms
     * @param {boolean} [turnOn] - Whether to make panel visible
     * @return {Promise} The result of the callback
     * @example
     *  GraphistryJS(document.getElementById('viz'))
     *     .flatMap(function (g) {
     *         window.g = g;
     *         console.log('opening histogram panel');
     *         return g.toggleHistograms(true);
     *     })
     *     .subscribe();
     */


    Graphistry.toggleHistograms = function toggleHistograms(turnOn) {
        var view = this.view;

        if (!turnOn) {
            return new this(view.set($value('panels.right', undefined), $value('histograms.controls[0].selected', false)).map(function (_ref13) {
                var json = _ref13.json;
                return json.toJSON();
            }).toPromise());
        } else {
            return new this(view.set($value('histograms.controls[0].selected', true), $value('panels.right', $ref(view._path.concat('histograms')))).map(function (_ref14) {
                var json = _ref14.json;
                return json.toJSON();
            }).toPromise());
        }
    };

    /**
     * Close the filters panel
     * @method Graphistry.closeFilters
     * @return {Promise} The result of the callback
     * @example
     * GraphistryJS(document.getElementById('viz'))
     *     .flatMap(function (g) {
     *         window.g = g;
     *         console.log('closing filters');
     *         return g.closeFilters();
     *     })
     *     .subscribe();
     */


    Graphistry.closeFilters = function closeFilters() {
        var view = this.view;

        return new this(view.set($value('panels.left', undefined), $value('filters.controls[0].selected', false)).map(function (_ref15) {
            var json = _ref15.json;
            return json.toJSON();
        }).toPromise());
    };

    /**
     * Run a number of steps of Graphistry's clustering algorithm
     * @method Graphistry.tickClustering
     * @static
     * @param {number} ticks - The number of ticks to run
     * @return {Promise} The result of the callback
     * @example
     * GraphistryJS(document.getElementById('viz'))
     *     .flatMap(function (g) {
     *         window.g = g;
     *         console.log('starting to cluster');
     *         return g.tickClustering();
     *     })
     *     .subscribe();
     */


    Graphistry.tickClustering = function tickClustering() {
        var ticks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;


        var obs = void 0;
        var view = this.view;


        if (typeof ticks !== 'number') {
            obs = Observable.of({});
        } else {
            obs = Observable.timer(0, 40).take(Math.abs(ticks) || 1).concatMap(function () {
                return view.call('tick', []);
            }).takeLast(1);
        }

        return new this(obs.toPromise());
    };

    /**
     * Center the view of the graph
     * @method Graphistry.autocenter
     * @static
     * @param {number} percentile - Controls sensitivity to outliers
     * @param {function} [cb] - Callback function of type callback(error, result)
     * @return {Promise} The result of the callback
     * @example
     * GraphistryJS(document.getElementById('viz'))
     *     .flatMap(function (g) {
     *         window.g = g;
     *         console.log('centering');
     *         return g.autocenter(.90);
     *     })
     *     .subscribe();
     */


    Graphistry.autocenter = function autocenter(percentile, cb) {};

    /**
     * Center the view of the graph
     * @method Graphistry.getCurrentWorkbook
     * @static
     * @param {function} [cb] - Callback function of type callback(error, result)
     * @return {Promise} The result of the callback
     * @example
     * GraphistryJS(document.getElementById('viz'))
     *     .flatMap(function (g) {
     *         window.g = g;
     *         return g.getCurrentWorkbook(function (err, obj){ alert('id: ' + obj.id); });
     *     })
     *     .subscribe();
     */


    Graphistry.getCurrentWorkbook = function getCurrentWorkbook() {
        var workbook = this.workbook;

        return new this(workbook.get('id').map(function (_ref16) {
            var json = _ref16.json;
            return json.toJSON();
        }).toPromise());
    };

    /**
     * Save the current workbook. A saved workbook will persist the analytics state
     * of the visualization, including active filters and exclusions
     * @method Graphistry.saveWorkbook
     * @static
     * @return {Promise} The result of the callback
     * @example
     * GraphistryJS(document.getElementById('viz'))
     *     .flatMap(function (g) {
     *         window.g = g;
     *         return g.saveWorkbook();
     *     })
     *     .subscribe();
     */


    Graphistry.saveWorkbook = function saveWorkbook() {
        var workbook = this.workbook;


        return new this(workbook.call('save', []).map(function (_ref17) {
            var json = _ref17.json;
            return json.toJSON();
        }).toPromise());
    };

    /**
     * Hide or Show Toolbar UI
     * @method Graphistry.toogleToolbar
     * @static
     * @param {boolean} show - Set to true to show toolbar, and false to hide toolbar.
     * @return {Promise} The result of the callback
     * @example
     *
     * <button onclick="window.graphistry.toggleToolbar(false)">Hide toolbar</button>
     * <button onclick="window.graphistry.toggleToolbar(true)">Show toolbar</button>
     *
     */


    Graphistry.toggleToolbar = function toggleToolbar(show) {
        return this.updateSetting('showToolbar', !!show);
    };

    /**
     * Add a filter to the visualization with the given expression
     * @method Graphistry.addFilter
     * @static
     * @param {string} expr - An expression using the same language as our in-tool
     * exclusion and filter panel
     * @return {Promise} The result of the callback
     * @example
     * graphistry.addFilter('degree > 0');
     */


    Graphistry.addFilter = function addFilter(expr) {
        var view = this.view;


        return new this(view.call('filters.add', [expr]).map(function (_ref18) {
            var json = _ref18.json;
            return json.toJSON();
        }).toPromise());
    };

    /**
     * Add an to the visualization with the given expression
     * @method Graphistry.addExclusion
     * @static
     * @param {string} expr - An expression using the same language as our in-tool
     * exclusion and filter panel
     * @return {Promise} The result of the callback
     * @example
     * graphistry.addExclusion('degree > 0');
     */


    Graphistry.addExclusion = function addExclusion(expr) {
        var view = this.view;


        return new this(view.call('exclusions.add', [expr]).map(function (_ref19) {
            var json = _ref19.json;
            return json.toJSON();
        }).toPromise());
    };

    /**
     * Add an to the visualization with the given expression
     * Key settings: showArrows, pruneOrphans, edgeOpacity, edgeSize, pointOpacity,
     * pointSize, labelOpacity, labelEnabled, labelPOI, zoom
     * @method Graphistry.updateSetting
     * @static
     * @param {string} name - the name of the setting to change
     * @param {string} val - the value to set the setting to.
     * @return {Promise} The result of the callback
     */


    Graphistry.updateSetting = function updateSetting(name, val) {

        var lookup = {

            //models/toolbar.js
            'showToolbar': ['view', 'toolbar.visible'],

            //models/scene/scene.js
            'pruneOrphans': ['view', 'pruneOrphans'],
            'showArrows': ['view', 'scene.renderer.showArrows'],
            'background': ['view', 'scene.renderer.background.color'],
            'edgeOpacity': ['view', 'scene.renderer.edges.opacity'],
            'edgeSize': ['view', 'scene.renderer.edges.scaling'],
            'pointOpacity': ['view', 'scene.renderer.points.opacity'],
            'pointSize': ['view', 'scene.renderer.points.scaling'],

            //models/camera.js
            'zoom': ['view', 'scene.camera.zoom'],
            'center': ['view', 'scene.camera.center["x", "y", "z"]'],

            //models/label.js
            'labelOpacity': ['view', 'scene.labels.opacity'],
            'labelEnabled': ['view', 'scene.labels.enabled'],
            'labelPOI': ['view', 'scene.labels.poiEnabled'],
            'labelColor': ['view', 'scene.labels.foreground.color'],
            'labelBackground': ['view', 'scene.labels.background.color'],

            //models/layout.js => viz-worker/simulator/layout.config.js:
            'precisionVsSpeed': ['view', 'layout.options.tau']

        };

        var _lookup$name = lookup[name],
            model = _lookup$name[0],
            path = _lookup$name[1];


        return new this(this[model].set($value(path, $atom(val, { $timestamp: Date.now() }))).map(function (_ref20) {
            var json = _ref20.json;
            return json.toJSON();
        }).toPromise());
    };

    /**
     * Add an to the visualization with the given expression
     * @method Graphistry.updateZoom
     * @static
     * @param {string} level - Controls how far to zoom in or out.
     * @param {string} val - the value to set the setting to.
     * @return {Promise} The result of the callback
     */


    Graphistry.updateZoom = function updateZoom(level) {
        return this.updateSetting('zoom', level);
    };

    /**
     * Subscribe to label events
     * @method Graphistry.subscribeLabels
     * @static
     * @param {subscriptions} subscriptions - A list of subscriptions that
     * will subscribe to any label updates
     * @return {Promise} The result of the callback
     */


    Graphistry.subscribeLabels = function subscribeLabels(_ref21) {
        var onChange = _ref21.onChange,
            onExit = _ref21.onExit;


        var labelsStream = this.labelsStream || (this.labelsStream = this.fromEvent(window, 'message').filter(function (_ref22) {
            var data = _ref22.data;
            return data && data.type === 'labels-update';
        }).map(function () {
            var _ref23 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
                data = _ref23.data;

            return data.labels || [];
        }).scan(function (sources, labels) {
            var _labels$reduce = labels.reduce(function (memo, label) {
                var id = label.id;
                var labelsById = memo.labelsById,
                    newSources = memo.newSources;


                var source = id in sources && sources[id] || new ReplaySubject(1);

                if (id in sources) {
                    delete sources[id];
                }

                labelsById[id] = label;
                newSources[id] = source;

                return memo;
            }, { labelsById: {}, newSources: _Object$create(null) }),
                labelsById = _labels$reduce.labelsById,
                newSources = _labels$reduce.newSources;

            for (var id in sources) {
                sources[id].complete();
            }

            for (var _id in newSources) {
                newSources[_id].next(labelsById[_id]);
            }

            return newSources;
        }, _Object$create(null)).multicast(function () {
            return new ReplaySubject(1);
        }).let(function (connectable) {
            connectable.connect();
            return connectable.refCount();
        }));

        return labelsStream.mergeMap(function (sources) {
            return _Object$keys(sources);
        }, function (sources, id) {
            return sources[id];
        }).mergeMap(function (group) {
            return group.do(function (_ref24) {
                var id = _ref24.id,
                    type = _ref24.type,
                    pageX = _ref24.pageX,
                    pageY = _ref24.pageY,
                    size = _ref24.size;
                return onChange && onChange(id, type, pageX, pageY, size);
            }).takeLast(1).do(function (_ref25) {
                var id = _ref25.id,
                    type = _ref25.type;
                return onExit && onExit(id, type);
            });
        }).subscribe();
    };

    return Graphistry;
}(Observable);

/**
 * Function that creates a Graphistry Wrapped IFrame
 * @func GraphistryJS
 * @param {Object} IFrame - An IFrame that incudes a Graphistry visualization.
 * @return {Graphistry}
 * @example
 *
 * <iframe id="viz" src="http://127.0.0.1:10000/graph/graph.html?dataset=Miserables" />
 * <script>
 * document.addEventListener("DOMContentLoaded", function () {
 *
 *     GraphistryJS(document.getElementById('viz'))
 *         .flatMap(function (g) {
 *             window.g = g;
 *             document.getElementById('controls').style.opacity=1.0;
 *             console.log('opening filters');
 *             return g.openFilters();
 *         })
 *         .delay(5000)
 *         .flatMap(function() {
 *             console.log('filters opened');
 *             const columns = [
 *                 ['edge', 'highways', [66, 101, 280], 'number'],
 *                 ['point', 'theme parks', ['six flags', 'disney world', 'great america'], 'string']
 *             ];
 *             console.log('adding columns', columns);
 *             return g.addColumns.apply(g, columns);
 *        })
 *         .subscribe(function (result) {
 *             console.log('all columns: ', result);
 *         });
 * });
 * </script>
 *
 */


Graphistry.view = null;
Graphistry.model = null;
Graphistry.workbook = null;
Graphistry.iFrame = null;
function GraphistryJS(iFrame) {

    if (!iFrame) {
        throw new Error('No iframe provided to Graphistry');
    }

    var model = new Model({
        recycleJSON: true,
        scheduler: Scheduler.async,
        allowFromWhenceYouCame: true
    });

    model._source = new PostMessageDataSource(window, iFrame.contentWindow, model);

    var InstalledGraphistry = function (_Graphistry) {
        _inherits(InstalledGraphistry, _Graphistry);

        function InstalledGraphistry() {
            _classCallCheck(this, InstalledGraphistry);

            return _possibleConstructorReturn(this, _Graphistry.apply(this, arguments));
        }

        InstalledGraphistry.prototype.lift = function lift(operator) {
            var observable = new InstalledGraphistry(this);
            observable.operator = operator;
            return observable;
        };

        return InstalledGraphistry;
    }(Graphistry);

    InstalledGraphistry.model = model;
    InstalledGraphistry.iFrame = iFrame;


    InstalledGraphistry = wrapStaticObservableMethods(Observable, InstalledGraphistry);

    return InstalledGraphistry.defer(function () {

        var initEvent = Observable.fromEvent(window, 'message').filter(function (_ref26) {
            var data = _ref26.data;
            return data && data.type === 'init';
        }).do(function (_ref27) {
            var data = _ref27.data;
            return model.setCache(data.cache);
        }).mergeMap(function (_ref28) {
            var data = _ref28.data;
            return model.get('workbooks.open.views.current.id');
        }, function (_ref29, _ref30) {
            var data = _ref29.data,
                source = _ref29.source;
            var json = _ref30.json;


            var workbook = json.workbooks.open;
            var view = workbook.views.current;

            InstalledGraphistry.workbook = model.deref(workbook);
            InstalledGraphistry.view = model.deref(view);

            console.log('initialized with view \'' + view.id + '\'');
            console.log('parent sending initialized message');

            source.postMessage({
                type: 'initialized',
                agent: 'graphistryjs',
                version: '2.11.194'
            }, '*');

            return InstalledGraphistry;
        }).take(1).multicast(new AsyncSubject());

        initEvent.connect();

        console.log('parent sending ready message');

        // trigger hello if missed initial one
        iFrame.contentWindow.postMessage({
            type: 'ready',
            agent: 'graphistryjs',
            version: '2.11.194'
        }, '*');

        return initEvent;
    });
}

import 'rxjs/add/operator/do';
import 'rxjs/add/operator/let';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/last';
import 'rxjs/add/operator/take';
import 'rxjs/add/operator/scan';
import 'rxjs/add/operator/takeLast';
import 'rxjs/add/operator/merge';
import 'rxjs/add/operator/concat';
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/finally';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/operator/concatMap';
import 'rxjs/add/operator/multicast';
import 'rxjs/add/operator/toPromise';
import 'rxjs/add/operator/takeUntil';

import 'rxjs/add/observable/of';
import 'rxjs/add/observable/from';
import 'rxjs/add/observable/defer';
import 'rxjs/add/observable/timer';
import 'rxjs/add/observable/merge';
import 'rxjs/add/observable/concat';
import 'rxjs/add/observable/fromEvent';
import 'rxjs/add/observable/bindCallback';

Graphistry = wrapStaticObservableMethods(Observable, Graphistry);

module.exports = GraphistryJS;
module.exports.GraphistryJS = GraphistryJS;

function wrapStaticObservableMethods(Observable, Graphistry) {
    function createStaticWrapper(staticMethodName) {
        return function () {
            return new Graphistry(Observable[staticMethodName].apply(Observable, arguments));
        };
    }
    for (var staticMethodName in Observable) {
        Graphistry[staticMethodName] = createStaticWrapper(staticMethodName);
    }
    Graphistry.bindCallback = function () {
        for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
            args[_key2] = arguments[_key2];
        }

        return function () {
            return new Graphistry(Observable.bindCallback.apply(Observable, args).apply(undefined, arguments));
        };
    };
    Graphistry.bindNodeCallback = function () {
        for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
            args[_key3] = arguments[_key3];
        }

        return function () {
            return new Graphistry(Observable.bindNodeCallback.apply(Observable, args).apply(undefined, arguments));
        };
    };
    return Graphistry;
}