'use strict'
const fs = require('fs');
const _ = require('lodash');


let configDefaults = require('./config.defaults');
if (fs.existsSync('./config.js'))
{
  let configChanges = require('./config');
  global.config = _.merge(configDefaults, configChanges);
}
else
  global.config = configDefaults;




const Repository = require('./lib/repository');
const NotificationWorker = require('./lib/workers/notification');
const ExpirationWorker = require('./lib/workers/expiration');

const express = require('express');
const bodyParser = require('body-parser');
const tus = require('tus-node-server');
const jwt = require('jsonwebtoken');
const path = require('path');
const resolvePath = require('resolve-path');
const cookieParser = require('cookie-parser');

const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');
const webpackConfigFactory = require('./webpack.config.js');


(async () =>
{
  try
  {
    const isDevelopment = process.env.NODE_ENV !== 'production';
    console.log('Running in ' + (isDevelopment ? 'development' : 'production') + ' mode');

    const repository = new Repository(config.database);
    await repository.load();

    const tusServer = new tus.Server();
    tusServer.datastore = new tus.FileStore({
        path: config.fileUpload.url,
        directory: config.fileUpload.path
    });

    const app = express();

    app.disable('x-powered-by');

    app.use(bodyParser.urlencoded({ extended: true }));
    app.use(bodyParser.json());
    app.use(cookieParser());



    app.use('/', require('./lib/api/upload')(repository, tusServer));
    app.use('/token', require('./lib/api/token')(repository));
    app.use('/admin', require('./lib/api/admin')(repository));


    // Frontend
    if (isDevelopment)
    {
      const webpackConfig = webpackConfigFactory(process.env, { mode: 'development' });
      const compiler = webpack(webpackConfig);

      app.use(webpackDevMiddleware(compiler, {
        publicPath: webpackConfig.output.publicPath
      }));

      app.use(webpackHotMiddleware(compiler));
    }


    // Automatic fallback support for file icons
    app.get('/images/fileicons/:format/:filename', (req, res) =>
    {
      var basePath;
      var filePath;

      try
      {
        basePath = resolvePath('./public/dist/images/fileicons/', req.params.format);
        filePath = resolvePath(basePath, req.params.filename);
      }
      catch (err)
      {
        res.sendStatus(404);
      }

      fs.stat(filePath, (err, stat) =>
      {
        if (err)
          res.sendFile(resolvePath(basePath, '_blank.png'));
        else
          res.sendFile(filePath);
      });
    });


    app.use(express.static(path.join(__dirname, 'custom')));
    app.use(express.static(path.join(__dirname, 'public', 'dist')));


    // Redirect to make Vue-router URLs less quirky
    app.get('/c/:code', (req, res) => { res.redirect(301, '/#/c/' + req.params.code) });


    // Background workers
    var notificationWorker = new NotificationWorker(repository);
    notificationWorker.start(config.notifications.interval * 1000);

    var expirationWorker = new ExpirationWorker(repository);
    expirationWorker.start(config.cleanupInterval * 1000);

    var server = app.listen(config.port, () => console.log('Recv running on port ' + server.address().port));
  }
  catch (e)
  {
    console.log(e);
    process.exit(1);
  }
})();