var http = require('http'),
    _ = require("underscore"),
    path = require("path")
    util = require('util'),
    find = require("shelljs").ls,
    runViaCli = require.main === module,
    options = {},
    optimist = null,
    fs = require("fs");

var routeMap = {};

/**
 * @param {Object} options
 * @property options.port {String}
 * @property options.tplDir {String}
 */
exports.init = function (opt) {

  options = opt;
  var tplDir = path.resolve(opt.tplDir);
  options.tplDir = tplDir;

  if (opt.routeMap) {
    routeMap = opt.routeMap;
  } else {
    routeMap = {
      "urlMatch": {
        regex: /^\/([\-0-9a-zA-Z]+)$/,
        handler: function (req, resp, routeName, matched) {
          var label = matched[1];
          var filepath = path.join(tplDir, label);

          // check if view dir exists
          if (fs.existsSync(filepath)) {
            app_handler(req, resp, routeName, matched, filepath);
          } else {
            notfound_handler(req, resp, routeName, matched, filepath);
          }
        }
      }
    };
  }

};

var log = function log() {
  if (runViaCli) {
    console.log.apply(console, arguments);
  }
};

exports.start = function() {
  var port = options.port;
  var s = http.createServer(function (req, res) {
    var found = false,
        routeName = "",
        matched = null;

    req.on('close', function(){
      log('premature close');
      res.end();
    });

    for (var routeName in routeMap) {
      matched = routeMap[routeName].regex.exec(req.url);
      if (matched) {
        found = true;
        s.emit('urlMatched', req, res, routeName, matched);
        break;
      }
    }

    if (!found) {
      res.writeHead(404);
      res.end();
    }
  });

  s.on('urlMatched', function(req, res, routeName, matched) {
    log('found match: ', matched[0]);
    routeMap[routeName].handler(req, res, routeName, matched);
  });

  s.port = port;
  s.url = 'http://localhost:' + port;

  s.listen(s.port, function() {
    log('server started: ', s.url);
  });

  return s;
};

function notfound_handler (req, resp, routeName, matched) {
  resp.writeHead(404);
  resp.end();
}

var get_file_list = exports.get_file_list = function (tplDir, label) {
  var filelist = find( '-R', path.join(tplDir, label) ).filter(function(file){ return file.match(/\.[a-zA-Z]+$/);});

  return _.map(filelist, function(item) {
    return item.split(path.sep);
  });
};


/**
 * @param {Object} obj
 * @param {Array} path
 * @return {Object}
 *
 * original obj = {}
 * [ 'a', 'b', 'c' ] => {a:{b:{c:{}}}}
 * [ 'a' ] => {}
 *
 * original obj = {a:{b:{c:'a'}}}
 * [ 'a', 'b', 'b' ] => {a:{b:{c:'a',b: {}}}}
 */
var create_object = exports.create_object = function (obj, path) {

  if (path.length && path.length == 1) {
    obj[path[0]] = obj[path[0]] ? obj[path[0]] : {};
    return obj[path[0]];
  }

  var marker = obj;
  var len = path.length;

  for (var i=0; i<len; i++) {
    if (!marker[path[i]]) {
      marker[path[i]] = {};
    }
    marker = marker[path[i]];
  }

  return marker;
};

function app_handler (req, resp, routeName, matched) {
  var label = matched[1];
  var filelist = get_file_list(options.tplDir, label);

  var obj = {};

  for (var i=0; i<filelist.length; i++) {
    if (filelist[i].length) {
      var filename = filelist[i].splice(filelist[i].length-1)[0];
      var marker = create_object(obj, filelist[i]);
      var fullpath = path.join(options.tplDir, label, filelist[i].join(path.sep), filename);
      var content = loadFile(fullpath);

      marker[filename.split('.')[0]] = content;
    }
  }

  resp.writeHead(200, {'Content-Type':'application/json'});
  resp.end(JSON.stringify(obj));
}

function loadFile (filename) {
  var content =  fs.readFileSync(filename, "utf8").toString();
  return content.trim();
}

@@ -264,16 +264,34 @@
 ap = %7B%7D;
+%0Avar servers = %5B%5D;
 %0A%0A/**%0A *
@@ -1197,24 +1197,44 @@
 unction() %7B%0A
+  var sockets = %5B%5D;%0A
   var port =
@@ -1756,24 +1756,44 @@
    %7D%0A  %7D);%0A%0A
+  servers.push(s);%0A%0A
   s.on('urlM
@@ -1956,147 +1956,678 @@
 %0A%0A  
-s.port = port;%0A  s.url = 'http://localhost:' + port;%0A%0A  s.listen(s.port, function() %7B%0A    log('server started: ', s.url);%0A  %7D);%0A%0A  return s
+// use this to track sockets%0A  s.on(%22connection%22, function(socket)%7B%0A    sockets.push(socket);%0A    socket.on('close', function()%7B%0A      sockets.splice(sockets.indexOf(socket), 1);%0A    %7D);%0A  %7D);%0A%0A  // cleanup sockets to properly shutdown server%0A  s.on(%22close%22, function() %7B%0A    log(%22cleaning up sockets%22);%0A    for (var i; i%3Csockets.length; i++) %7B%0A      sockets%5Bi%5D.destroy();%0A    %7D%0A  %7D);%0A%0A  s.port = port;%0A  s.url = 'http://localhost:' + port;%0A%0A  s.listen(s.port, function() %7B%0A    log('server started: ', s.url);%0A  %7D);%0A%0A  return s;%0A%7D;%0A%0Aexports.closeAll = function() %7B%0A  for (var i=0; i%3Cservers.length; i++) %7B%0A    servers%5Bi%5D.close();%0A  %7D%0A  log(%22server terminated. Good bye%22)
 ;%0A%7D;

add method to gracefully close server