// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
"use strict";
var utils = require('./utils');
var shims;
(function (shims) {
    var services;
    (function (services) {
        /**
         * Public constructor
         * @param jsServicesKernel - jupyter-js-services IKernel instance
         */
        var CommManager = (function () {
            function CommManager(jsServicesKernel) {
                this.targets = Object.create(null);
                this.kernel = null;
                this.jsServicesKernel = null;
                this.init_kernel(jsServicesKernel);
            }
            ;
            /**
             * Hookup kernel events.
             * @param  {IKernel} jsServicesKernel - jupyter-js-services IKernel instance
             */
            CommManager.prototype.init_kernel = function (jsServicesKernel) {
                this.kernel = jsServicesKernel; // These aren't really the same.
                this.jsServicesKernel = jsServicesKernel;
            };
            ;
            /**
             * Creates a new connected comm
             * @param  {string} target_name
             * @param  {object} data
             * @param  {object} callbacks
             * @param  {object} metadata
             * @param  {string} comm_id
             * @return {Comm}
             */
            CommManager.prototype.new_comm = function (target_name, data, callbacks, metadata, comm_id) {
                var comm = new Comm(this.jsServicesKernel.connectToComm(target_name, comm_id));
                comm.open(data, callbacks, metadata);
                return comm;
            };
            ;
            /**
             * Register a comm target
             * @param  {string} target_name
             * @param  {(Comm, object) => void} f - callback that is called when the
             *                         comm is made.  Signature of f(comm, msg).
             */
            CommManager.prototype.register_target = function (target_name, f) {
                var handle = this.jsServicesKernel.registerCommTarget(target_name, function (jsServicesComm, msg) {
                    // Create the comm.
                    var comm = new Comm(jsServicesComm);
                    // Call the callback for the comm.
                    try {
                        return f(comm, msg);
                    }
                    catch (e) {
                        comm.close();
                        var wrapped_error = new utils.WrappedError('Exception opening new comm', e);
                        console.error(wrapped_error);
                        return;
                    }
                });
                this.targets[target_name] = handle;
            };
            ;
            /**
             * Unregisters a comm target
             * @param  {string} target_name
             */
            CommManager.prototype.unregister_target = function (target_name, f) {
                var handle = this.targets[target_name];
                handle.dispose();
                delete this.targets[target_name];
            };
            ;
            return CommManager;
        }());
        services.CommManager = CommManager;
        /**
         * Public constructor
         * @param  {IComm} jsServicesComm - jupyter-js-services IComm instance
         */
        var Comm = (function () {
            function Comm(jsServicesComm) {
                this.jsServicesComm = null;
                this.jsServicesComm = jsServicesComm;
            }
            Object.defineProperty(Comm.prototype, "comm_id", {
                /**
                 * Comm id
                 * @return {string}
                 */
                get: function () {
                    return this.jsServicesComm.commId;
                },
                enumerable: true,
                configurable: true
            });
            Object.defineProperty(Comm.prototype, "target_name", {
                /**
                 * Target name
                 * @return {string}
                 */
                get: function () {
                    return this.jsServicesComm.targetName;
                },
                enumerable: true,
                configurable: true
            });
            /**
             * Opens a sibling comm in the backend
             * @param  data
             * @param  callbacks
             * @param  metadata
             * @return msg id
             */
            Comm.prototype.open = function (data, callbacks, metadata) {
                var future = this.jsServicesComm.open(data, metadata);
                this._hookupCallbacks(future, callbacks);
                return future.msg.header.msg_id;
            };
            ;
            /**
             * Sends a message to the sibling comm in the backend
             * @param  data
             * @param  callbacks
             * @param  metadata
             * @param  buffers
             * @return message id
             */
            Comm.prototype.send = function (data, callbacks, metadata, buffers) {
                var future = this.jsServicesComm.send(data, metadata, buffers);
                this._hookupCallbacks(future, callbacks);
                return future.msg.header.msg_id;
            };
            ;
            /**
             * Closes the sibling comm in the backend
             * @param  data
             * @param  callbacks
             * @param  metadata
             * @return msg id
             */
            Comm.prototype.close = function (data, callbacks, metadata) {
                var future = this.jsServicesComm.close(data, metadata);
                this._hookupCallbacks(future, callbacks);
                return future.msg.header.msg_id;
            };
            ;
            /**
             * Register a message handler
             * @param  callback, which is given a message
             */
            Comm.prototype.on_msg = function (callback) {
                this.jsServicesComm.onMsg = callback.bind(this);
            };
            ;
            /**
             * Register a handler for when the comm is closed by the backend
             * @param  callback, which is given a message
             */
            Comm.prototype.on_close = function (callback) {
                this.jsServicesComm.onClose = callback.bind(this);
            };
            ;
            /**
             * Hooks callback object up with jupyter-js-services IKernelFuture
             * @param  jupyter-js-services IKernelFuture instance
             * @param  callbacks
             */
            Comm.prototype._hookupCallbacks = function (future, callbacks) {
                if (callbacks) {
                    future.onReply = function (msg) {
                        if (callbacks.shell && callbacks.shell.reply)
                            callbacks.shell.reply(msg);
                        // TODO: Handle payloads.  See https://github.com/jupyter/notebook/blob/master/notebook/static/services/kernels/kernel.js#L923-L947
                    };
                    future.onStdin = function (msg) {
                        if (callbacks.input)
                            callbacks.input(msg);
                    };
                    future.onIOPub = function (msg) {
                        if (callbacks.iopub) {
                            if (callbacks.iopub.status && msg.header.msg_type === 'status') {
                                callbacks.iopub.status(msg);
                            }
                            else if (callbacks.iopub.clear_output && msg.header.msg_type === 'clear_output') {
                                callbacks.iopub.clear_output(msg);
                            }
                            else if (callbacks.iopub.output) {
                                switch (msg.header.msg_type) {
                                    case 'display_data':
                                    case 'execute_result':
                                        callbacks.iopub.output(msg);
                                        break;
                                }
                                ;
                            }
                        }
                    };
                }
            };
            ;
            return Comm;
        }());
        services.Comm = Comm;
    })(services = shims.services || (shims.services = {}));
})(shims = exports.shims || (exports.shims = {}));
