var WebSocketServer = require("ws").Server;
var util = require("util");
var async = require("async");
var _ = require("lodash");

var shlog = require(global.gBaseDir + "/src/shlog.js");
var sh = require(global.gBaseDir + "/src/shutil.js");
var ShLoader = require(global.gBaseDir + "/src/shloader.js");
var channel = require(global.gBaseDir + "/functions/channel/channel.js");

var Socket = exports;
var wss = null;

function add(data) {
  if (data.event === "error") {
    shlog.error(data);
  }
  sh.sendWs(this.ws, 0, data);
}

function fillSession(sess, req, res, cb) {
  sh.fillSession(sess, req, res, function (error, data) {
    if (req.session.valid) {
      res.ws.uid = req.session.uid;
      res.ws.name = req.session.user.get("name");
      return cb(0);
    }
    return cb(1); // no valid session
  });
}

function handleConnect(ws) {
  shlog.info("socket: connect");
  ws.uid = 0;
  ws.games = [];
  ws.hbTimer = null;

  var loader = new ShLoader();

  var heartBeat = function () {
    sh.sendWs(ws, 0, sh.event("heartbeat", {interval: global.CONF.heartBeat}));
  };
  ws.hbTimer = setInterval(heartBeat, global.CONF.heartBeat);

  ws.on("message", function (data) {
    shlog.recv("live - %s", data);
    // parse packet
    var packet = {};
    try {
      packet = JSON.parse(data);
    } catch (err) {
      sh.sendWs(ws, 1, sh.error("socket", "unable to parse json message", { message: err.message, stack: err.stack }));
      return;
    }

    var loader = new ShLoader();
    var req = {session: {valid: false}, body: {}, loader: loader};
    var res = {ws: ws, add: add};

    var msgs = null;
    if (_.isArray(packet.batch)) {
      msgs = packet.batch;
    } else {
      msgs = [packet];
    }

    fillSession(packet.session, req, res, function (err) {
      // session.valid now used to control access to functions
      try {
        // process each message with same loader
        async.eachSeries(msgs, function (item, cb) {
          req.body = item;
          sh.call(req, res, function (err, data) {
            cb(err);
          });
        }, function (err) {
          loader.dump();  // don't wait on dump cb
        });
      } catch (err1) {
        sh.sendWs(ws, 1, sh.error("socket", "message - " + err1.message, { message: err1.message, stack: err1.stack }));
      }
    });
  });  // end ws.on-message

  ws.on("error", function (err) {
    shlog.error("(" + this.uid + ")", err);
  });

  ws.on("close", function () {
    shlog.info("(" + this.uid + ") socket: close");

    clearInterval(this.hbTimer);

    // clean up any channels
    _.each(ws.channels, function (value, key) {
      shlog.info("removing", key);
      channel.removeInt(ws, key);
    });
  });
}

Socket.start = function () {
  wss = new WebSocketServer({port: global.CONF.socketPort});
  shlog.info("socketserver listening: " + global.CONF.socketPort);
  var connCount = 1;

  wss.on("connection", function (ws) {
    ws.id = connCount;
    connCount += 1;
    ws.channels = {};
    try {
      handleConnect(ws);
    } catch (err) {
      sh.sendWs(ws, 1, sh.error("socket", "connection - " + err.message, { message: err.message, stack: err.stack }));
    }
  }); // end wss.on-connection

  wss.on("error", function (err) {
    shlog.error(err);
  });
};

Socket.close = function (cb) {
  try {
    wss.close();
  } catch (e) {
    // do not care ws lib does not allow bind check via address() call
  }
  cb();
};

@@ -527,297 +527,8 @@
 %0A%7D%0A%0A
-function fillSession(sess, req, res, cb) %7B%0A  sh.fillSession(sess, req, res, function (error, data) %7B%0A    if (req.session.valid) %7B%0A      res.ws.uid = req.session.uid;%0A      res.ws.name = req.session.user.get(%22name%22);%0A      return cb(0);%0A    %7D%0A    return cb(1); // no valid session%0A  %7D);%0A%7D%0A%0A
 func
@@ -552,16 +552,16 @@
 t(ws) %7B%0A
+
   shlog.
@@ -1163,24 +1163,45 @@
 urn;%0A    %7D%0A%0A
+    // setup req/res%0A
     var load
@@ -1323,16 +1323,36 @@
  add%7D;%0A%0A
+    // handle batch%0A
     var 
@@ -1473,16 +1473,19 @@
  %7D%0A%0A    
+sh.
 fillSess
@@ -1540,16 +1540,20 @@
      // 
+req.
 session.
@@ -1588,21 +1588,137 @@
 cess
- to functions
+%0A      if (req.session.valid) %7B%0A        res.ws.uid = req.session.uid;%0A        res.ws.name = req.session.user.get(%22name%22);%0A      %7D
 %0A   

remove extra fillSession function;