const express = require('express');
const asyncHandler = require('express-async-handler');
const jwt = require('jsonwebtoken');
const resolvePath = require('resolve-path');
const fs = require('fs');
const async = require('async');
const NotificationType = require('../repository/notification').NotificationType;


async function checkAuthorization(req, res, onVerified)
{
  if (!req.headers.authorization || req.headers.authorization.split(' ')[0] !== 'Bearer')
  {
    res.sendStatus(400);
    return;
  }

  var token = req.headers.authorization.split(' ')[1];
  jwt.verify(token, config.jwtSecret, async (err, decoded) =>
  {
    try
    {
      if (err)
      {
        res.sendStatus(403);
        return;
      }

      if (decoded.codeId)
        await onVerified(decoded);
      else
        res.sendStatus(400);
    }
    catch (e)
    {
      console.log(e);
      res.sendStatus(500);
    }
  });
}



module.exports = (repository, tusServer) =>
{
  var router = express.Router();

  // Upload API
  router.get('/info/:code', asyncHandler(async (req, res) =>
  {
    var code = await repository.codes.get(req.params.code);
    if (code === null)
    {
      res.sendStatus(404);
      return;
    }

    let info = {
      message: null,
      expirationDate: code.expirationDate,
      expiration: code.expiration
    };

    if (code.messageHTML)
    {
      var user = await repository.users.get(code.userId);
      var name = user !== null ? user.name : null;

      info.message = {
        name: name,
        message: code.messageHTML
      };
    }

    res.send(info);
  }));

  router.post('/complete', asyncHandler(async (req, res) =>
  {
    if (!req.body.files)
    {
      res.sendStatus(400);
      return;
    }

    await checkAuthorization(req, res, async (decoded) =>
    {
      async.each(req.body.files, (item, callback) =>
      {
        if (!item.id)
        {
          callback();
          return;
        }

        var fullpath = resolvePath(config.fileUpload.path, item.id);
        fs.stat(fullpath, (err, stats) =>
        {
          item.size = stats.size;
          callback();
        });
      },
      async (err) =>
      {
        if (err)
        {
          res.sendStatus(500);
          return;
        }

        let expirationDate = await repository.codes.getUploadExpirationDate(decoded.codeId);

        var uploadId = await repository.uploads.insert({
          userId: decoded.codeUserId,
          codeId: decoded.codeId,
          files: req.body.files,
          expirationDate: expirationDate
        });

        await repository.notifications.insert({
          userId: decoded.codeUserId,
          uploadId: uploadId,
          type: NotificationType.UploadComplete
        });

        res.send({ id: uploadId });
      });
    });
  }));


  // Tus upload
  const uploadApp = express();
  uploadApp.all('*', asyncHandler(async (req, res) =>
  {
    await checkAuthorization(req, res, async (decoded) =>
    {
      tusServer.handle(req, res);
    });
  }));

  router.use('/upload', uploadApp);
  return router;
}