text: "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  const net = require("net");
  const node_1 = require("./node");
  const socket_handler_1 = require("../core/socket-handler");
  const global_1 = require("../core/global");
  const logging_helper_1 = require("../core/logging-helper");
  const statistics_1 = require("./statistics");
  const Logger = "NODEMGR";
  class NodeManager {
      constructor(port) {
          this.port = port;
          this.host = "0.0.0.0";
          this.onConnect = null;
          this.onNodeRemoved = null;
          this.nodes = {};
      }
      node(nodeID) {
          return this.nodes[nodeID];
      }
      start(callback) {
          const self = this;
          this.server = net.createServer(function (socket) {
              let initialConnection = true;
              let node = null;
              const socketHandler = new socket_handler_1.SocketHandler(socket, function (socketMessage) {
                  const strMessage = socketMessage.asString();
                  if (initialConnection) {
                      if (!socketMessage.isJSON()) {
                          logging_helper_1.LoggingHelper.error(Logger, "Error on parsing initial message: " + strMessage);
                          socketHandler.disconnect();
                          return;
                      }
                      const connectData = socketMessage.asJSON();
                      node = new node_1.Node(connectData.id, socketHandler);
                      self.nodes[node.id] = node;
                      socketHandler.send(new socket_handler_1.SocketMessage("ACK"));
                      initialConnection = false;
                      if (self.onConnect != null) {
                          self.onConnect(node);
                      }
                      statistics_1.Statistics.instance().record(node.id, statistics_1.AccessType.CONNECT);
                  }
                  else if (strMessage === global_1.Global.KeepAliveMessage) {
                      NodeManager.onKeepAliveReceived(node);
                  }
                  else if (node.handlingRequest()) {
                      node.onReply(socketMessage);
                  }
              });
              socketHandler.onCloseCallback = function () {
                  if (node !== null) {
                      logging_helper_1.LoggingHelper.info(Logger, "NODE CLOSED: " + node.id);
                      delete self.nodes[node.id];
                      if (self.onNodeRemoved !== undefined && self.onNodeRemoved !== null) {
                          self.onNodeRemoved(node);
                      }
                  }
              };
              logging_helper_1.LoggingHelper.info(Logger, "NODE CONNECTED: " + socket.remoteAddress + ":" + socket.remotePort);
          }).listen(this.port, this.host);
          this.server.on("listening", function () {
              if (callback !== undefined && callback !== null) {
                  callback();
              }
          });
          logging_helper_1.LoggingHelper.info(Logger, "Listening on " + this.host + ":" + this.port);
      }
      static onKeepAliveReceived(node) {
          node.socketHandler.send(new socket_handler_1.SocketMessage(global_1.Global.KeepAliveMessage));
      }
      stop(callback) {
          for (let key of Object.keys(this.nodes)) {
              const node = this.node(key);
              node.socketHandler.disconnect();
              logging_helper_1.LoggingHelper.info(Logger, "NODE CLOSING: " + node.id);
          }
          this.server.close(function (error) {
              if (error !== undefined) {
                  logging_helper_1.LoggingHelper.error(Logger, "ERROR! NodeManager not stopped: " + error);
              }
              else {
                  logging_helper_1.LoggingHelper.info(Logger, "STOPPED");
                  callback();
              }
          });
      }
  }
  exports.NodeManager = NodeManager;
  //# sourceMappingURL=node-manager.js.map