function PersistentConnectionSR(options) {
    this._dataUltimaAtualizacao = new Date().getTime();
    this._handlers = ko.observableArray([]);
    this._mapeamento = options.mapeamento;
    this._limiteMaximoSemAtualizacao = 3 * 60 * 1000; // 3 minutos
    this._tempoCicloVerificacao = 60 * 1000; // 1 minuto
    this._poolingDivLog = "poolingDivLog";
    this._limiteEsperandoAtualizacao = 5;
    this._options = options;
    this._lastGuid = "";
    this.init();
    try {
        this.pingTimeout = new PingTimeOut(this, 2000);
    } catch (Exc) { }
};

PersistentConnectionSR.prototype.timeoutCallBack = function (self) {
    self.init();
};

PersistentConnectionSR.prototype.init = function () {
    $('body').append("<div id='" + this._poolingDivLog + "' class='hide'></div>");
    this._conn = $.connection(this._mapeamento);
    var self = this;
    this._conn.received(self);
    this._conn.start({ transport: 'webSockets' }).done(function() { self.onConnected(); });
    this._conn.reconnected(function () { self.onReconnected(); });
    $(this._conn).bind("onDisconnect", function (e, data) {
        self.onDisconnect(self._conn);
        if (self.pingTimeout) {
            self.pingTimeout.Init();
        }
    });
};

PersistentConnectionSR.prototype.onDisconnect = function () {
    var self = this;
    self.log("SignalR Desconectado!");
    self._conectado = false;

    setTimeout(function () {
        if (self._conectado == false) {
            self._conn.start({ transport: 'webSockets' });
            self.log("SignalR Conectado novamente!");
        }
    }, 3000);
};

PersistentConnectionSR.prototype.getMapeamento = function () {
    return this._mapeamento;
};

PersistentConnectionSR.prototype.log = function (mensagem) {
    console.log(mensagem);
};

PersistentConnectionSR.prototype.call = function(connection, evento) {

    if (evento) {
        this._dataUltimaAtualizacao = new Date().getTime();

        try {
            if (this._handlers().length > 0) {
                ko.utils.arrayForEach(this._handlers(), function (handler) {
                    handler.TratarEvento(evento.Evento, evento.Mensagem);
                });
            }
        } catch (Exception) {
            this.error(Exception);
            this.log("Erro OnDataReceived: [" + Exception + "] JSON [" + evento.Mensagem + "] TIPO [" + evento.Evento + "]");
        }
    }
};

PersistentConnectionSR.prototype.error = function (Exception) {
    console.error(Exception);
};

PersistentConnectionSR.prototype.GetId = function () {
    return this._conn.id;
};

PersistentConnectionSR.prototype.enviarFiltro = function (filtro) {
    this.Send(JSON.stringify({ Objeto: filtro, Tipo: 4 }));
    this.log("Filtro enviado!");
};

PersistentConnectionSR.prototype.Send = function (obj) {
    if (poolingTempoReal._conn.state == 1) {
        this._conn.send(obj);
    }
    else {
        var self = this;
        setTimeout(function () { self.Send(obj); }, 1000);
    }
};

PersistentConnectionSR.prototype.trocaDeGuid = function (lasGuid) {
    this._conn.send(JSON.stringify({ Tipo: 5, Objeto: lasGuid }));
    this.log("solicitar troca de guid enviada!");
};


PersistentConnectionSR.prototype.onReconnected = function () {
    if (this._lastGuid != "" && this._lastGuid != this._conn.id) {
        var self = this;
        var funcaoReconectar = function () { self._conn.send(JSON.stringify({ Tipo: 5, Objeto: self._lastGuid })); };
        setTimeout(funcaoReconectar, 2000);
        this._lastGuid = this._conn.id;
    }
    this.log('SignalR Reconectado');
};

PersistentConnectionSR.prototype.onConnected = function () {
    if (this._options && this._options.onConnected) {
        this._options.onConnected();
    }

    if (this._lastGuid != "" && this._lastGuid != this._conn.id) {
        var self = this;
        var guid = self._lastGuid;
        var func = function () { self.trocaDeGuid(guid) };
        setTimeout(func, 2000);
    }

    this._lastGuid = this._conn.id;
    this.log("SignalR Conectado!");
};

PersistentConnectionSR.prototype.SetHandlers = function (handler) {
    this._handlers.push(handler);
};
