'use strict';

process.env.TZ = 'Etc/GMT';

console.log('Loading Goodtimes');

const express = require('express'),
  bodyParser = require('body-parser'),
  config = require('config'),
  session = require('express-session'),
  sqliteStoreFactory = require('express-session-sqlite').default,
  basePath = require('./basepath'),
  app = express(),
  csrf = require('csurf'), 
  http = require('http'),
  methodOverride = require('method-override'),
  cookieParser = require('cookie-parser'),
  { goodTimesDB } = require('./db.js'),
  sqlite3 = require('sqlite3'),
  SqliteStore = sqliteStoreFactory(session);

require('./console-line.js'); /* Monkey-patch console.log with line numbers */

/* App is behind an nginx proxy which we trust, so use the remote address
 * set in the headers */
app.set('trust proxy', true);
app.use(session({
  secret: 'm@g1x!c00k13$',
  maxAge: 14 * 24 * 60 * 60 * 1000, /* 2 weeks */
  resave: true,
  saveUninitialized: false,
  cookie: { secure: true },
  store: new SqliteStore({
    driver: sqlite3.Database,
    path: config.get('sessions.db'),
    ttl: 5000,
    cleanupInterval: 300000
  }),
}));

app.use(bodyParser.urlencoded({ extended: false }));
app.use((req, res, next) => {
  console.log('CSRF debug: ', {
    token: req.header('CSRF-Token'), 
    method: req.method
  });
  next();
});
app.use(cookieParser());
app.use(csrf({
  cookie: true
}));
app.use(bodyParser.json());

//const ws = require('express-ws')(app, server);

/* Initialize the data base, configure routes, and open server */
goodTimesDB.init().then((db) => {
  console.log('DB connected. Configuring routes.');
  
  app.locals.db = db;
  app.set('basePath', basePath);

  app.use(`${basePath}api/v1/groups`, require('./routes/groups'));
  app.use(`${basePath}api/v1/users`, require('./routes/users'));

  /* Error handler and catch for 404 */
  app.use(methodOverride());
  app.use((err, req, res, next) => {
    console.log('CSRF debug: ', {
      token: req.header('CSRF-Token'),
      csrf: req.csrfToken(),
      method: req.method
    });
    console.error(err);
    res.status(err.status || 500).json({
      message: err.message,
      error: {}
    });
  });
}).then(() => {
  const server = http.createServer(app),
    serverConfig = config.get('server');

  console.log('Hosting server from: ' + basePath);
  app.set('port', serverConfig.port);

  process.on('SIGINT', () => {
    console.log('Gracefully shutting down from SIGINT (Ctrl-C) in 2 seconds');
    setTimeout(() => process.exit(-1), 2000);
    server.close(() => process.exit(1));
  });

  server.on('error', function (error) {
    if (error.syscall !== 'listen') {
      throw error;
    }

    // handle specific listen errors with friendly messages
    switch (error.code) {
    case 'EACCES':
      console.error(serverConfig.port + ' requires elevated privileges');
      process.exit(1);
      break;
    case 'EADDRINUSE':
      console.error(serverConfig.port + ' is already in use');
      process.exit(1);
      break;
    default:
      throw error;
    }
  });
  server.listen(serverConfig.port, () => {
    console.log(`http server listening on ${serverConfig.port}`);
  });
});