var path = require('path');
var lowdb = require('lowdb');
var express = require('express');
var udb = require('underscore-db');
var bodyParser = require('body-parser');
var session = require('express-session');

var app = express();
var router = express.Router();
var cmsdb = lowdb('./db.json');
var userdb = lowdb('./users.json');
var installing = false;
var server = app.listen(80);

init();

function init() {
  addDatabaseMixins();
  maybeEnterInstallationMode();
  addMiddlewares();
  serveStaticStuff();
  denyUnauthenticatedWrites(); // Must run before handlers!
  handleGet();
  handlePost();
  handlePut();
  handleDelete();
}

function addDatabaseMixins() {
  cmsdb._.mixin(udb);
  cmsdb._.mixin(udb);
}

function maybeEnterInstallationMode() {
  var admins = userdb('admins');
  if (!Array.isArray(admins) || admins.size() < 1) {
    console.log('No admin accounts found. Entering Installation mode.');
    console.log('Visit /install to create an account.');
    installing = true;
  }
}

function addMiddlewares() {
  app.use(bodyParser.json());
  app.use(session({
    secret: 'tall gels',
    resave: false,
    saveUninitialized: false
  }));
  app.use('/api', router);
}

function serveStaticStuff() {
  app.use(express.static(path.resolve(__dirname, 'static/')));
  app.use(express.static(path.resolve(process.cwd(), 'public/')));
}

function denyUnauthenticatedWrites() {
  router.use(function(req, res, next) {
    if (req.method === 'GET' || req.session.user) next();
    else res.status(403).end();
  });
}

function handleGet() {
  router.get('/:resource', function(req, res) {
    res.json(cmsdb(req.params.resource));
    console.log('Route /:resource | r: '+req.params.resource);
  });

  router.get('/:resource/:id', function(req, res) {
    var id = toIntIfValid(req.params.id);
    var result = cmsdb(req.params.resource).getById(id);
    if (result) res.json(result);
    else res.status(404).end();
    console.log('Route /:resource/:id | r: '+req.params.resource+' id: '+id);
  });
}

function handlePost() {
  router.post('/:resource', function(req, res) {
    var resources = cmsdb(req.params.resource);
    var id = toIntIfValid(req.body.id);
    if (id !== undefined && resources.getById(id)) res.status(409).end();
    else {
      resources.insert(req.body);
      res.end();
    }
    console.log('Route /:resource | r: '+req.params.resource+' id: '+id);
  });
}

function handlePut() {
  router.put('/:resource', function(req, res) {
    var resources = cmsdb(req.params.resource);
    var result = resources.updateById(req.body.id, req.body);
    if (result) res.end();
    else res.status(404).end();
    console.log('PUT /:resource | r: '+req.params.resource+' id: '+req.body.id);
  });
}

function handleDelete() {
  router.delete('/:resource/:id', function(req, res) {
    var resources = cmsdb(req.params.resource);
    var id = toIntIfValid(req.params.id);
    var result = resources.removeById(id);
    if (result) res.end();
    else res.status(404).end();
    console.log('DELETE /:resource/:id | r: '+req.params.resource+' id: '+id);
  });
}

function toIntIfValid(input) {
  return isInteger(input)? parseInt(input) : input;
}

function isInteger(input) {
  var regex = /^(0|[1-9][0-9]*)$/;
  return regex.test(input);
}
@@ -503,16 +503,42 @@
 tuff();%0A
+  handleAuthentication();%0A
   denyUn
@@ -542,32 +542,35 @@
 yUnauthenticated
+Api
 Writes(); // Mus
@@ -596,24 +596,27 @@
 rs!%0A  handle
+Api
 Get();%0A  han
@@ -614,24 +614,27 @@
 ();%0A  handle
+Api
 Post();%0A  ha
@@ -633,24 +633,27 @@
 ();%0A  handle
+Api
 Put();%0A  han
@@ -651,24 +651,27 @@
 ();%0A  handle
+Api
 Delete();%0A%7D%0A
@@ -1382,24 +1382,541 @@
 ic/')));%0A%7D%0A%0A
+function handleAuthentication() %7B%0A  app.post('/cmssy/admins', function(req, res) %7B%0A    var admins = userdb('admins');%0A    var username = req.body.username;%0A    var password = req.body.password;%0A    if (!installing) res.status(403).end();%0A    else if (!username %7C%7C !password) res.status(400).end();%0A    else %7B%0A      var current = admins.findWhere(%7Busername: username%7D);%0A      if (current) admins.updateWhere(%7Busername: username%7D, req.body);%0A      else admins.insert(req.body);%0A      installing = false;%0A    %7D%0A  %7D);%0A%7D%0A%0A
 function den
@@ -1931,16 +1931,19 @@
 nticated
+Api
 Writes()
@@ -2099,16 +2099,19 @@
 n handle
+Api
 Get() %7B%0A
@@ -2589,16 +2589,19 @@
 n handle
+Api
 Post() %7B
@@ -2978,16 +2978,19 @@
 n handle
+Api
 Put() %7B%0A
@@ -3288,32 +3288,32 @@
 y.id);%0A  %7D);%0A%7D%0A%0A
-
 function handleD
@@ -3311,16 +3311,19 @@
 n handle
+Api
 Delete()

Allow creation of new account via API