var http = require('http');
var url = require('url');
var fs = require('fs');

var winston = require('winston');
var connect = require('connect');

var DocumentHandler = require('./lib/document_handler');

// Load the configuration and set some defaults
var config = JSON.parse(fs.readFileSync('config.js', 'utf8'));
config.port = config.port || 7777;
config.host = config.host || 'localhost';

// Set up the logger
if (config.logging) {
  try {
    winston.remove(winston.transports.Console);
  } catch(er) { }
  var detail, type;
  for (var i = 0; i < config.logging.length; i++) {
    detail = config.logging[i];
    type = detail.type;
    delete detail.type;
    winston.add(winston.transports[type], detail);
  }
}

// build the store from the config on-demand - so that we don't load it
// for statics
if (!config.storage) {
  config.storage = { type: 'file' };
}
if (!config.storage.type) {
  config.storage.type = 'file';
}
var Store = require('./lib/document_stores/' + config.storage.type);
var preferredStore = new Store(config.storage);

// Compress the static javascript assets
if (config.recompressStaticAssets) {
  var jsp = require("uglify-js").parser;
  var pro = require("uglify-js").uglify;
  var list = fs.readdirSync('./static');
  for (var i = 0; i < list.length; i++) {
    var item = list[i];
    var orig_code, ast;
    if ((item.indexOf('.js') === item.length - 3) &&
        (item.indexOf('.min.js') === -1)) {
      dest = item.substring(0, item.length - 3) + '.min' +
        item.substring(item.length - 3);
      orig_code = fs.readFileSync('./static/' + item, 'utf8');
      ast = jsp.parse(orig_code);
      ast = pro.ast_mangle(ast);
      ast = pro.ast_squeeze(ast);
      fs.writeFileSync('./static/' + dest, pro.gen_code(ast), 'utf8');
      winston.info('compressed ' + item + ' into ' + dest);
    }
  }
}

// Send the static documents into the preferred store, skipping expirations
for (var name in config.documents) {
  var path = config.documents[name];
  fs.readFile(path, 'utf8', function(err, data) {
    if (data && !err) {
      preferredStore.set(name, data, function(cb) {
        winston.info('loaded static document', { name: name, path: path });
      }, true);
    }
    else {
      winston.warn(
        'failed to load static document',
        { name: name, path: path }
      );
    }
  });
}

// Pick up a key generator
var pwOptions = config.keyGenerator || {};
pwOptions.type = pwOptions.type || 'random';
var gen = require('./lib/key_generators/' + pwOptions.type);
var keyGenerator = new gen(pwOptions);

// Configure the document handler
var documentHandler = new DocumentHandler({
  store: preferredStore,
  maxLength: config.maxLength,
  keyLength: config.keyLength,
  keyGenerator: keyGenerator
});

// Set the server up with a static cache
connect.createServer(
  // First look for api calls
  connect.router(function(app) {
    // get raw documents - support getting with extension
    app.get('/raw/:id', function(request, response, next) {
      var skipExpire = !!config.documents[request.params.id];
      var key = request.params.id.split('.')[0];
      return documentHandler.handleRawGet(key, response, skipExpire);
    });
    // add documents
    app.post('/documents', function(request, response, next) {
      return documentHandler.handlePost(request, response);
    });
    // get documents
    app.get('/documents/:id', function(request, response, next) {
      var skipExpire = !!config.documents[request.params.id];
      return documentHandler.handleGet(
        request.params.id,
        response,
        skipExpire
      );
    });
  }),
  // Otherwise, static
  connect.staticCache(),
  connect.static(__dirname + '/static', { maxAge: config.staticMaxAge }),
  // Then we can loop back - and everything else should be a token,
  // so route it back to /index.html
  connect.router(function(app) {
    app.get('/:id', function(request, response, next) {
      request.url = request.originalUrl = '/index.html';
      next();
    });
  }),
  connect.static(__dirname + '/static', { maxAge: config.staticMaxAge })
).listen(config.port, config.host);

winston.info('listening on ' + config.host + ':' + config.port);
