var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
(function (factory) {
    if (typeof module === "object" && typeof module.exports === "object") {
        var v = factory(require, exports);
        if (v !== undefined) module.exports = v;
    }
    else if (typeof define === "function" && define.amd) {
        define(["require", "exports", "./Base", "@dojo/core/async/Task", "@dojo/shim/global", "../browser/util"], factory);
    }
})(function (require, exports) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    var Base_1 = require("./Base");
    var Task_1 = require("@dojo/core/async/Task");
    var global_1 = require("@dojo/shim/global");
    var util_1 = require("../browser/util");
    var WebSocketChannel = (function (_super) {
        __extends(WebSocketChannel, _super);
        function WebSocketChannel(options) {
            var _this = _super.call(this, options) || this;
            if (_this.timeout == null) {
                _this.timeout = 1000;
            }
            if (!options.port) {
                throw new Error('A port is required for a WebSocket channel');
            }
            var url = util_1.parseUrl(options.url);
            var host = url.hostname;
            var protocol = url.protocol === 'https' ? 'wss' : 'ws';
            _this._socket = new global_1.default.WebSocket(protocol + "://" + host + ":" + options.port);
            _this._ready = new Task_1.default(function (resolve, reject) {
                _this._socket.addEventListener('open', resolve);
                _this._socket.addEventListener('error', reject);
            });
            _this._socket.addEventListener('message', function (event) {
                _this._handleMessage(JSON.parse(event.data));
            });
            _this._socket.addEventListener('error', function (_event) {
                _this._handleError(new Error('WebSocket error'));
            });
            _this._sendQueue = {};
            _this._sequence = 1;
            return _this;
        }
        WebSocketChannel.prototype._sendData = function (name, data) {
            var _this = this;
            return this._ready.then(function () { return new Task_1.default(function (resolve, reject) {
                var id = String(_this._sequence++);
                var sessionId = _this.sessionId;
                var message = { id: id, sessionId: sessionId, name: name, data: data };
                _this._socket.send(JSON.stringify(message));
                var timer = setTimeout(function () {
                    reject(new Error('Send timed out'));
                }, _this.timeout);
                _this._sendQueue[id] = {
                    resolve: function () {
                        clearTimeout(timer);
                        resolve();
                    },
                    reject: function (error) {
                        reject(error);
                    }
                };
            }); });
        };
        WebSocketChannel.prototype._handleMessage = function (message) {
            var id = message.id;
            this._sendQueue[id].resolve();
            this._sendQueue[id] = undefined;
        };
        WebSocketChannel.prototype._handleError = function (error) {
            var _this = this;
            // Make the _ready task a reject to reject future _sendData calls
            this._ready = Task_1.default.reject(error);
            // Reject any open sends
            Object.keys(this._sendQueue).filter(function (id) { return _this._sendQueue[id] != null; }).forEach(function (id) {
                _this._sendQueue[id].reject(error);
                _this._sendQueue[id] = undefined;
            });
        };
        return WebSocketChannel;
    }(Base_1.default));
    exports.default = WebSocketChannel;
});
//# sourceMappingURL=WebSocket.js.map