const asyncHandler = require('express-async-handler');
const AuthTokens = require('../../authtokens');
const ExpirationUnits = require('../../expirationunits');
const NotificationType = require('../../repository/notification').NotificationType;
const _ = require('lodash');


module.exports = (repository, router) =>
{
  router.get('/codes', asyncHandler(async (req, res) =>
  {
    var codes = await repository.codes.list(req.user.hasAuth(AuthTokens.ViewAllCodes) ? null : req.user.id);
    var usernames = await repository.users.getNames();

    codes.forEach((item) =>
    {
      item.username = usernames[item.userId];
    });

    res.send(codes);
  }));


  router.get('/codes/:id', asyncHandler(async (req, res) =>
  {
    var code = await repository.codes.get(req.params.id);
    if (code === null || (code.userId !== req.user.id && !req.user.hasAuth(AuthTokens.ViewAllCodes)))
    {
      res.sendStatus(404);
      return;
    }

    var user = await repository.users.get(code.userId);
    if (user !== null)
      code.username = user.name;

    res.send(code);
  }));


  router.post('/codes', asyncHandler(async (req, res) =>
  {
    var postedCode = req.body;


    if (config.code.maxExpiration !== null)
    {
      let now = new Date();

      if (ExpirationUnits.apply(postedCode.expiration) > ExpirationUnits.apply(config.code.maxExpiration))
      {
        res.sendStatus(400);
        return;
      }
    }


    if (postedCode.id)
    {
      var code = await repository.codes.get(postedCode.id);
      if (code === null || (code.userId !== req.user.id && !req.user.hasAuth(AuthTokens.ViewAllCodes)))
      {
        res.sendStatus(404);
        return;
      }

      await repository.codes.update({
        id: postedCode.id,
        expiration: postedCode.expiration,
        description: postedCode.description,
        message: postedCode.message
      });

      res.sendStatus(200);
    }
    else
    {
      var codeId = await repository.codes.insert({
        userId: req.user.id,
        created: postedCode.created || new Date(),
        expiration: postedCode.expiration,
        description: postedCode.description,
        message: postedCode.message
      });
    }

    res.send(codeId);
  }));


  router.delete('/codes/:id', asyncHandler(async (req, res) =>
  {
    var code = await repository.codes.get(req.params.id);
    if (code == null || (code.userId !== req.user.id && !req.user.hasAuth(AuthTokens.ViewAllCodes)))
    {
      res.sendStatus(404);
      return;
    }

    repository.codes.delete(code.id);
    res.sendStatus(200);
  }));


  router.get('/expiration', asyncHandler(async (req, res) =>
  {
    res.send({
      max: config.code.maxExpiration,
      default: config.code.defaultExpiration
    });
  }));


  router.post('/assign/code', asyncHandler(async (req, res) =>
  {
    var postedCode = req.body;

    var code = await repository.codes.get(postedCode.id);
    if (code === null || (code.userId !== req.user.id && !req.user.hasAuth(AuthTokens.ViewAllCodes)))
    {
      res.sendStatus(404);
      return;
    }

    if (code.userId !== postedCode.userId)
    {
      var target = await repository.users.get(postedCode.userId);
      if (target === null)
      {
        res.sendStatus(400);
        return;
      }

      await repository.codes.move(postedCode.id, postedCode.userId);
      await repository.uploads.move(postedCode.id, postedCode.userId);

      await repository.notifications.insert({
        userId: postedCode.userId,
        codeId: postedCode.id,
        type: NotificationType.CodeMoved,
        metadata: {
          prevUserId: code.userId,
          assignUserId: req.user.id
        }
      });
    }

    res.sendStatus(200);
  }));


  router.get('/assign/users', asyncHandler(async (req, res) =>
  {
    var users = await repository.users.list();
    if (users === null)
    {
      res.send([]);
      return;
    }

    let assignableUsers = _.map(_.filter(users,
      (user) => { return user.active }),
      (user) => { return {
        id: user.id,
        username: user.username,
        name: user.name
      }} );

    res.send(assignableUsers);
  }));
}