docs: function(params, callback) {
          /**
           * This callback Returns error or contact list.
           * @callback chatConnectCallback
           * @param {Object} error - The error object
           * @param {(Object|Boolean)} response - Object of subscribed users (roster) or empty body.
           * */
          Utils.QBLog('[QBChat]', 'Connect with parameters ' + JSON.stringify(params));
  
          var self = this,
              userJid = chatUtils.buildUserJid(params),
              isInitialConnect = typeof callback === 'function',
              err;
  
          if (self._isConnecting) {
              err = Utils.getError(422, 'Status.REJECT - The connection is still in the Status.CONNECTING state', 'QBChat');
  
              if (isInitialConnect) {
                  callback(err, null);
              }
  
              return;
          }
  
          if (self.isConnected) {
              Utils.QBLog('[QBChat]', 'Status.CONNECTED - You are already connected');
  
              if (isInitialConnect) {
                  callback(null, self.roster.contacts);
              }
  
              return;
          }
  
          self._isConnecting = true;
          self._isLogout = false;
  
          /** Connect for browser env. */
          if (Utils.getEnv().browser) {
              self.connection.connect(userJid, params.password, function(status) {
                  switch (status) {
                      case Strophe.Status.ERROR:
                          self.isConnected = false;
                          self._isConnecting = false;
  
                          err = Utils.getError(422, 'Status.ERROR - An error has occurred', 'QBChat');
  
                          if (isInitialConnect) {
                              callback(err, null);
                          }
  
                          break;
                      case Strophe.Status.CONNFAIL:
                          self.isConnected = false;
                          self._isConnecting = false;
                          
                          err = Utils.getError(422, 'Status.CONNFAIL - The connection attempt failed', 'QBChat');
                          
                          if (isInitialConnect) {
                              callback(err, null);
                          }
                          
                          break;
                      case Strophe.Status.AUTHENTICATING:
                          Utils.QBLog('[QBChat]', 'Status.AUTHENTICATING');
  
                          break;
                      case Strophe.Status.AUTHFAIL:
                          self.isConnected = false;
                          self._isConnecting = false;
                          
                          err = Utils.getError(401, 'Status.AUTHFAIL - The authentication attempt failed', 'QBChat');
                          
                          if (isInitialConnect) {
                              callback(err, null);
                          }
                          
                          if(!self.isConnected && typeof self.onReconnectFailedListener === 'function'){
                              Utils.safeCallbackCall(self.onReconnectFailedListener, err);
                          }
                          
                          break;
                      case Strophe.Status.CONNECTING:
                          Utils.QBLog('[QBChat]', 'Status.CONNECTING', '(Chat Protocol - ' + (config.chatProtocol.active === 1 ? 'BOSH' : 'WebSocket' + ')'));
              
                          break;
                      case Strophe.Status.CONNECTED:
                          // Remove any handlers that might exist from a previous connection via
                          // extension method added to the connection on initialization in qbMain.
                          // NOTE: streamManagement also adds handlers, so do this first.
                          self.connection.XDeleteHandlers();
                          
                          self.connection.XAddTrackedHandler(self._onMessage, null, 'message', 'chat');
                          self.connection.XAddTrackedHandler(self._onMessage, null, 'message', 'groupchat');
                          self.connection.XAddTrackedHandler(self._onPresence, null, 'presence');
                          self.connection.XAddTrackedHandler(self._onIQ, null, 'iq');
                          self.connection.XAddTrackedHandler(self._onSystemMessageListener, null, 'message', 'headline');
                          self.connection.XAddTrackedHandler(self._onMessageErrorListener, null, 'message', 'error');
                      
                          self._postConnectActions(function(roster) {
                              callback(null, roster);
                          }, isInitialConnect);
  
                          break;
                      case Strophe.Status.DISCONNECTING:
                          Utils.QBLog('[QBChat]', 'Status.DISCONNECTING');
                          break;
                      case Strophe.Status.DISCONNECTED:
                          Utils.QBLog('[QBChat]', 'Status.DISCONNECTED at ' + chatUtils.getLocalTime());
  
                          // fire 'onDisconnectedListener' only once
                          if (self.isConnected && typeof self.onDisconnectedListener === 'function'){
                              Utils.safeCallbackCall(self.onDisconnectedListener);
                          }
  
                          self.isConnected = false;
                          self._isConnecting = false;
  
                          // reconnect to chat and enable check connection
                          self._establishConnection(params);
  
                          break;
                      case Strophe.Status.ATTACHED:
                          Utils.QBLog('[QBChat]', 'Status.ATTACHED');
                          break;
                  }
              });
          }
  
          /** connect for node */
          if(!Utils.getEnv().browser) {
              // Remove all connection handlers exist from a previous connection
              self.Client.removeAllListeners();
  
              self.Client.on('connect', function() {
                  Utils.QBLog('[QBChat]', 'Status.CONNECTING', '(Chat Protocol - ' + (config.chatProtocol.active === 1 ? 'BOSH' : 'WebSocket' + ')'));
              });
  
              self.Client.on('auth', function() {
                  Utils.QBLog('[QBChat]', 'Status.AUTHENTICATING');
              });
                      
              self.Client.on('online', function() {
                  self._postConnectActions(function(roster) {
                      callback(null, roster);
                  }, isInitialConnect);
              });
      
              self.Client.on('stanza', function(stanza) {
                  Utils.QBLog('[QBChat] RECV:', stanza.toString());
                  /**
                   * Detect typeof incoming stanza
                   * and fire the Listener
                   */
                  if (stanza.is('presence')) {
                      self._onPresence(stanza);
                  } else if (stanza.is('iq')) {
                      self._onIQ(stanza);
                  } else if(stanza.is('message')) {
                      if (stanza.attrs.type === 'headline') {
                          self._onSystemMessageListener(stanza);
                      } else if(stanza.attrs.type === 'error') {
                          self._onMessageErrorListener(stanza);
                      } else {
                          self._onMessage(stanza);
                      }
                  }
              });
              
              self.Client.on('disconnect', function() {
                  Utils.QBLog('[QBChat]', 'Status.DISCONNECTED - ' + chatUtils.getLocalTime());
  
                  if (typeof self.onDisconnectedListener === 'function') {
                      Utils.safeCallbackCall(self.onDisconnectedListener);
                  }
                  
                  self.isConnected = false;
                  self._isConnecting = false;
  
                  // reconnect to chat and enable check connection
                  self._establishConnection(params);
              });
              
              self.Client.on('error', function() {
                  Utils.QBLog('[QBChat]', 'Status.ERROR - ' + chatUtils.getLocalTime());
                  err = Utils.getError(422, 'Status.ERROR - An error has occurred', 'QBChat');
      
                  if (isInitialConnect) {
                      callback(err, null);
                  }
  
                  self.isConnected = false;
                  self._isConnecting = false;
              });
  
              self.Client.on('end', function() {
                  self.Client.removeAllListeners();                
              });
  
              self.Client.options.jid = userJid;
              self.Client.options.password = params.password;
              self.Client.connect();
          }
      }