#!/usr/bin/env node

/* global require, process, module */

// require()s
var path = require('path');
var fs = require('fs');

var _ = require('lodash');
var chokidar = require('chokidar');
var debug = require('debug')('cheese:cli');

var server = require('../lib/server.js');

// opt parsing
var usage = 'Usage: cheese [<port>] [--dev|-d]\n'
          + '       cheese [--help|-h]\n\n'
          + 'Start a cheese server in the current directory.\n'
          + '<port> is the port to listen on, defaults to 3000.';

var opt = require('yargs')
          .usage(usage)
          .boolean('help')
          .alias('help', 'h')
          .describe('help', 'Show this help message and exit')
          .boolean('dev')
          .alias('dev', 'd')
          .describe('dev', 'Reload the server and reload browsers '
                         + 'automatically when files change');

if (opt.argv.help) {
  opt.showHelp();
  process.exit(0);
}

var port = opt.argv.port || 3000;

// startServer: start a server in directory 'dirname', listening
// on port 'port'. 'reload' is an optional argument used when
// the server is reloaded.
function startServer (dirname, port, reload, done) {
  debug('starting server on port ' + port);

  if (! reload) reload = false;

  var jsonString = fs.readFileSync(path.join(dirname, 'cheese.json'),
                                   { encoding: 'utf-8' });
  var mainFilePath = JSON.parse(jsonString).main;
  var clientFiles = JSON.parse(jsonString).client;
  var clientPaths = [];
  var clientData = '';
  var staticData = {};

  if (mainFilePath)
    mainFilePath = path.resolve(path.join(dirname, mainFilePath));

  clientFiles = _.map(clientFiles, function (p) {
    return path.join(dirname, p);
  });

  // traverseDir: traverse a directory tree and return a list
  // of files.
  var traverseDir = function (d) {
    var files = fs.readdirSync(d);
    var finalList = [];
    _.each(files, function (elem, index, list) {
      if (fs.statSync(path.join(d, elem)).isDirectory())
        finalList = finalList.concat(traverseDir(path.join(d, elem)));
      else finalList.push(path.join(d, elem));
    });

    return finalList;
  };

  _.each(clientFiles, function (p) {
    if (fs.statSync(p).isDirectory()) clientPaths = clientPaths.concat(traverseDir(p));
    else clientPaths.push(p);
  });

  _.each(clientPaths, function (elem, index, list) {
    // we assume that file names ending with 'js' aren't static content
    if (_.last(elem.split('.')) === 'js')
      clientData += '\n' + fs.readFileSync(elem, { 'encoding': 'utf-8' });
    else
      staticData[elem] = fs.readFileSync(elem, { 'encoding': 'utf-8' });
  });

  if (! reload)
    server.start(port, clientData, staticData, mainFilePath, done);
  else server.reload(clientData, staticData, mainFilePath);

  return server;
}

// watchFiles: set up a file watcher to reload the server every time
// a file in 'dirname' changes.
function watchFiles (dirname) {
  var watcher = chokidar.watch(dirname, { ignoreInitial: true });

  watcher.on('all', function (change, filepath) {
    filepath = path.join(dirname, filepath);

    var cheeseJSON = fs.readFileSync(path.join(dirname, 'cheese.json'),
                                     { encoding: 'utf-8' });
    var clientFiles = JSON.parse(cheeseJSON).client;
    var mainFile;

    if (JSON.parse(cheeseJSON).main)
      mainFile = path.join(dirname, JSON.parse(cheeseJSON).main);

    clientFiles = _.map(clientFiles, function (p) {
      return path.join(dirname, p);
    });

    var listed = _.some(_.map(clientFiles, function (p) {
      return _.contains(path.resolve(filepath), p);
    }));

    // only reload when changes are made to files listed in cheese.json
    if (listed || mainFile === filepath ||
        path.basename(filepath) === 'cheese.json') {
      debug('reloading server');
      startServer(dirname, port, true);
    }
  });

  return watcher;
}

module.exports = {
  startServer: startServer,
  watchFiles: watchFiles
};

if (require.main === module) {
  startServer('.', port);
  if (opt.argv.dev) watchFiles('.');
}

@@ -332,24 +332,66 @@
 -dev%7C-d%5D%5Cn'%0A
+          + '       cheese %5B--version%5D%5Cn'%0A
           + 
@@ -418,24 +418,24 @@
 lp%7C-h%5D%5Cn%5Cn'%0A
-
           + 
@@ -724,16 +724,109 @@
  exit')%0A
+          .boolean('version')%0A          .describe('version', 'Show version number and exit')%0A
         
@@ -1025,16 +1025,16 @@
 help) %7B%0A
-
   opt.sh
@@ -1065,16 +1065,191 @@
 (0);%0A%7D%0A%0A
+if (opt.argv.version) %7B%0A  var packageJson = fs.readFileSync(path.join(__dirname, '..', 'package.json'));%0A  console.log(JSON.parse(packageJson).version);%0A  process.exit(0);%0A%7D%0A%0A
 var port

add --version option to cli