"use strict";

const Package = require('@sex-pomelo/sex-pomelo-protocol').Package;
const logger = require('@sex-pomelo/sex-pomelo-logger').getLogger('pomelo', __filename);

/**
 * Process heartbeat request.
 *
 * @param {Object} opts option request
 *                      opts.heartbeat heartbeat interval
 */
let Command = function(opts) {
  opts = opts || {};
  this.heartbeat = null;
  this.timeout = null;
  this.disconnectOnTimeout = opts.disconnectOnTimeout;

  if(opts.heartbeat) {
    this.heartbeat = opts.heartbeat * 1000; // heartbeat interval
    this.timeout = opts.timeout * 1000 || this.heartbeat * 2;      // max heartbeat message timeout
    this.disconnectOnTimeout = true;
  }

  this.timeouts = {};
  this.clients = {};
};

module.exports = Command;

Command.prototype.handle = function(socket) {
  if(!this.heartbeat) {
    // no heartbeat setting
    return;
  }

  let self = this;

  if(!this.clients[socket.id]) {
    // clear timers when socket disconnect or error
    this.clients[socket.id] = 1;
    socket.once('disconnect', clearTimers.bind(null, this, socket.id));
    socket.once('error', clearTimers.bind(null, this, socket.id));
  }

  // clear timeout timer
  if(self.disconnectOnTimeout) {
    this.clear(socket.id);
  }

  socket.sendRaw(Package.encode(Package.TYPE_HEARTBEAT));

  if(self.disconnectOnTimeout) {
    self.timeouts[socket.id] = setTimeout(function() {
      logger.info('client %j heartbeat timeout.', socket.id);
      socket.disconnect();
    }, self.timeout);
  }
};

Command.prototype.clear = function(id) {
  let tid = this.timeouts[id];
  if(tid) {
    clearTimeout(tid);
    delete this.timeouts[id];
  }
};

let clearTimers = function(self, id) {
  delete self.clients[id];
  let tid = self.timeouts[id];
  if(tid) {
    clearTimeout(tid);
    delete self.timeouts[id];
  }
};