//Dependencies
var app               = require('express')(),
    _                 = require('underscore'),
    server            = require('http').createServer(app),
    io                = require('socket.io').listen(server),
    redis             = require('redis'),
    moment            = require('moment'),
    yaml              = require('js-yaml'),
    fs                = require('fs');

//Configuation
var pubsub_prefix     = 'socketio.',
    redis_conf        = yaml.safeLoad(fs.readFileSync('./redis.yml', 'utf8')),
    node_env          = process.env.NODE_ENV          || 'development',
    port              = redis_conf[node_env]['port']  || 6379,
    host              = redis_conf[node_env]['host']  || 'localhost',
    //A connection to redis is either in "subscriber" mode or "regular" mode
    //So we have both a "subcriber" client and "regular" client
    subscriber_redis  = redis.createClient(port, host),
    commander_redis   = redis.createClient(port, host);

var log = function(msg) {if (node_env == 'development') console.log('['+moment().format('h:mm:ss a')+'] '+msg);};
var get = function(key, callback) {
  if (commander_redis.connected)
    commander_redis.get(key, callback); //(GET) That's why we need a "regular" client
  else
    log('Trying to get ['+key+'], but Redis is disconnected. Returning null instead.');
}

// Not binding the 'error' event will cause node to stop when Redis is unreachable
commander_redis.on('error',   function (err)  {log('La connection à Redis a échoué: ['+err+']');});
subscriber_redis.on('error',  function (err)  {log('La connection à Redis a échoué: ['+err+']');});
subscriber_redis.on('end',    function ()     {log('La connection à Redis a été coupé.');});
subscriber_redis.on('ready',  function ()     {log('Redis est prêt à recevoir des requêtes.');

  subscriber_redis.psubscribe(pubsub_prefix + '*');
  subscriber_redis.on('pmessage',function(pat, ch, msg) {
    log('subscriber_redis: pat:'+JSON.stringify(pat)+' ch:'+JSON.stringify(ch)+' msg:'+JSON.stringify(msg));
    io.sockets.in(ch).send(msg);
  });

});




io.sockets.on('connection', function (socket) {

  socket.on('register', function (data)
  {
    log('register : '+JSON.stringify(data));
    if (data['channels'] && _.isArray(data['channels']))
    {
      _.each(data['channels'], function(channel)
      {
        //On register we check if there is a persistant key [channel]
        //There is one if a publishing/cloning is going on
        get(pubsub_prefix + channel, function (err, value) {
            if (err) throw(err);
            if (value != null) socket.send(value);
        });
        socket.join(pubsub_prefix + channel);
      });
    }
  });

  socket.on('unregister', function (data)
  {
    log('unregister : '+JSON.stringify(data));
    if (data['channels'] && _.isArray(data['channels']))
    {
      _.each(data['channels'], function(channel) {
        socket.leave(pubsub_prefix + channel);
      });
    }
  });

});




server.listen(8889, 'localhost');
log("listenning on localhost:8889");