const services = require('../services')
const events = require('events');
const random_bytes = require('random-bytes');

const emitter = new events.EventEmitter();

const { longpolling } = services

const poll_server_timeout = 20000;
const poll_client_timeout = 60000;

poll_request_event_identifier = function (id) { return ('poll-request-' + id).toLowerCase(); }
poll_response_event_identifier = function (qid) { return ('poll-response-' + qid).toLowerCase(); }

poll_request = function (method, action, id, device, data, callback) {
  function request_listener(message) {
    ///// Stop timeout
    clearTimeout(timeout);
    callback(null, message);
  };

  ///// Create object
  object = {
    method: method,
    nsip: device || '',
    action: action || '/',
    data: JSON.stringify(data).replace(/"/g, "'") || '{}',
    qid: random_bytes.sync(16).toString('hex')
  };

  ///// Wait long polling to open
  emitter.emit(poll_request_event_identifier(id), object);

  ///// Start timeout
  var timeout = setTimeout(() => {
    ///// Remove listener
    emitter.removeListener(poll_response_event_identifier(object.qid), request_listener);

    ///// Send timeout
    console.log(id + ' did not long poll (' + object.qid + ')');
    callback('timeout', null);
  }, poll_client_timeout);

  ///// Listen for event
  emitter.once(poll_response_event_identifier(object.qid), request_listener);
}

const postPeriodic = async (req, res, next) => {
  function listener(message) {
    ///// Stop timeout
    clearTimeout(timeout);

    ///// Send response
    res.send(message);
  };

  ///// Start timeout
  var timeout = setTimeout(() => {
    ///// Remove listener
    emitter.removeListener(poll_request_event_identifier(req.params.id), listener);

    ///// Send timeout
    res.sendStatus(408);
    console.log('Sending timeout to client ' + req.ip + ' (' + req.params.id + ')');
  }, poll_server_timeout);

  ///// Listen for event
  emitter.once(poll_request_event_identifier(req.params.id), listener);
}

const postResponse = async (req, res, next) => {
  ///// Emit event to client
  emitter.emit(poll_response_event_identifier(req.params.qid), req.body);

  ///// Response OK
  res.sendStatus(200);
}

const getModuleRequest = async (req, res, next) => {
  ///// Emit event to server
  url_encoded = req.query;
  poll_request(req.method, req.params.route, req.params.id, req.params.module, url_encoded, (error, body) => {
    if (error) { res.send(error); }
    else { res.send(body); }
  });

  req.on("close", function () {
    console.log("Request cancelled by client");
  });
}

const postModuleRequest = async (req, res, next) => {
  ///// Emit event to server
  poll_request(req.method, req.params.route, req.params.id, req.params.module, req.body, (error, body) => {
    if (error) { res.send(error); }
    else { res.send(body); }
  });

  req.on("close", function () {
    console.log("Request cancelled by client");
  });
}

module.exports = {
  postPeriodic,
  postResponse,
  getModuleRequest,
  postModuleRequest
}