'use strict';

var cluster = require('cluster');
var PromiseA = require('bluebird');
var path = require('path');
var os = require('os');

function init(conf, state) {
  var newConf = {};

  function rand(n) {
    var HEX = 16;
    var BASE_36 = 36;
    var rnd = require('crypto').randomBytes(n || 16).toString('hex');
    return parseInt(rnd, HEX).toString(BASE_36);
  }

  if (!conf.ipcKey) {
    conf.ipcKey = newConf.ipcKey = rand(16);
  }
  if (!conf.sqlite3Sock) {
    conf.sqlite3Sock = newConf.sqlite3Sock = path.join(os.tmpdir(), 'sqlite3.' + rand(8) + '.sock');
  }
  if (!conf.memstoreSock) {
    conf.memstoreSock = newConf.memstoreSock = path.join(os.tmpdir(), 'memstore.' + rand(8) + '.sock');
  }

  try {
    require('fs').unlinkSync(conf.memstoreSock);
  } catch(e) {
    if ('ENOENT' !== e.code) {
      console.error(e.stack);
      console.error(JSON.stringify(e));
    }
    // ignore
  }
  try {
    require('fs').unlinkSync(conf.sqlite3Sock);
  } catch(e) {
    if ('ENOENT' !== e.code) {
      console.error(e.stack);
      console.error(JSON.stringify(e));
    }
    // ignore
  }

  var cstore = require('cluster-store');
  var sqlite3 = require('sqlite3-cluster/server');
  var cstoreOpts = {
    sock: conf.memstoreSock
  , serve: cluster.isMaster && conf.memstoreSock
  , store: cluster.isMaster && null //new require('express-session/session/memory')()
  // TODO implement
  , key: conf.ipcKey
  };
  var cstorePromise = cstore.create(cstoreOpts);
  var promise = PromiseA.all([
    cstorePromise.then(function (store) {
      console.log('[walnut] [master] cstore created');
      //console.log(cstoreOpts);
      //console.log(store);
      return store;
    })
  , sqlite3.createServer({
      verbose: null
    , sock: conf.sqlite3Sock
    , ipcKey: conf.ipcKey
    })/*.then(function () {
      var sqlite3 = require('sqlite3-cluster/client');
      return sqliet3.createClientFactory(...);
    })*/
  ]).then(function (args) {
    state.memstore = args[0];
    //state.sqlstore = args[1];
    newConf.addWorker = function (w) {
      return cstorePromise.addWorker(w);
    };
    return newConf;
  });

  return promise;
}

function touch(conf, state) {
  if (!state.initialize) {
    state.initialize = init(conf, state);
  }

  // TODO if no xyz worker, start on xyz worker (unlock, for example)
  return state.initialize.then(function (newConf) {
    // TODO conf.locked = true|false;
    conf.initialized = true;
    return newConf;
  });
}

module.exports.init = init;
module.exports.touch = touch;
