var RobustEventSource = (function () {
    function RobustEventSource(url) {
        this._explictClosed = false;
        this._listenerLists = Object.create(null);
        this._tryRecover = this._tryRecover.bind(this);
        this._tryRecover0 = this._tryRecover0.bind(this);
        this._init(url);
    }
    Object.defineProperty(RobustEventSource.prototype, "url", {
        get: function () { return this._backEnd.url; },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(RobustEventSource.prototype, "withCredentials", {
        get: function () { return this._backEnd.withCredentials; },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(RobustEventSource.prototype, "onopen", {
        get: function () { return this._backEnd.onopen; },
        set: function (listener) { this._backEnd.onopen = listener; },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(RobustEventSource.prototype, "onmessage", {
        get: function () { return this._backEnd.onmessage; },
        set: function (listener) { this._backEnd.onmessage = listener; },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(RobustEventSource.prototype, "onerror", {
        get: function () { return this._backEnd.onerror; },
        set: function (listener) { this._backEnd.onerror = listener; },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(RobustEventSource.prototype, "readyState", {
        get: function () {
            if (this._backEnd.readyState == 2 && !this._explictClosed)
                return 0;
            return this._backEnd.readyState;
        },
        enumerable: true,
        configurable: true
    });
    RobustEventSource.prototype.addEventListener = function (type, listener, useCapture) {
        this._backEnd['_addEventListener'](type, listener, useCapture);
        var list = this._getListenerList(type, useCapture);
        if (list.indexOf(listener) >= 0)
            list.push(listener);
    };
    RobustEventSource.prototype.dispatchEvent = function (evt) {
        return this._backEnd.dispatchEvent(evt);
    };
    RobustEventSource.prototype.removeEventListener = function (type, listener, useCapture) {
        this._backEnd['_removeEventListener'](type, listener, useCapture);
        var list = this._getListenerList(type, useCapture);
        var i = list.indexOf(listener);
        if (i >= 0)
            list.splice(i, 1);
    };
    RobustEventSource.prototype.close = function () {
        if (!this._explictClosed) {
            this._explictClosed = true;
            this._backEnd['_close']();
            this._backEnd['_removeEventListener']('error', this._tryRecover);
            self.removeEventListener('online', this._tryRecover);
        }
    };
    RobustEventSource.prototype._init = function (url) {
        var _this = this;
        this._backEnd = new EventSource(url);
        ['close', 'addEventListener', 'removeEventListener'].forEach(function (method) {
            _this._backEnd['_' + method] = _this._backEnd[method];
            _this._backEnd[method] = _this[method].bind(_this);
        });
        this._backEnd['_addEventListener']('error', this._tryRecover);
        self.addEventListener('online', this._tryRecover);
    };
    RobustEventSource.prototype._tryRecover = function (evt) {
        setTimeout(this._tryRecover0, 3000);
    };
    RobustEventSource.prototype._tryRecover0 = function (evt) {
        var _this = this;
        if (!this._explictClosed && this._backEnd.readyState == 2) {
            var old = this._backEnd;
            this._init(old.url);
            this._backEnd.onerror = old.onerror;
            this._backEnd.onmessage = old.onmessage;
            this._backEnd.onopen = old.onopen;
            ['open', 'message', 'error'].forEach(function (type) {
                [true, false].forEach(function (useCapture) {
                    _this._getListenerList(type, useCapture).forEach(function (listener) {
                        _this._backEnd.addEventListener(type, listener, useCapture);
                    });
                });
            });
        }
    };
    RobustEventSource.prototype._getListenerList = function (type, useCapture) {
        var key = type + ':' + !!useCapture;
        return this._listenerLists[key] || (this._listenerLists[key] = []);
    };
    return RobustEventSource;
})();
