const minisign = require('minisign');
const fs = require('fs');
const sodium = require('sodium-native');

module.exports = function(options) {
  options = options || {};
  options.sendFileOptions = options.sendFileOptions || {};
  options.signContentOptions = options.signContentOptions || {};

  if (options.minisignPassword === undefined) {
    throw new Error('missing: minisignPassword.  A password for your minisign installation must be supplied');
  }

  if (options.minisignSecretKeyFilePath === undefined) {
    throw new Error('missing: minisignSecretKeyFilePath.  The filepath for your minisign secret key must be supplied');
  }

  if (typeof options.serveFile !== 'function' && options.filePath === undefined) {
    throw new Error('missing: A function to serve your file, or a static filePath should be supplied');
  }

  if (typeof options.serveFile === 'function' && options.filePath !== undefined) {
    throw new Error('Either a static filePath should be supplied OR a serveFile function');
  }

  return function(req, res, next) {
    let file;
    if (options.serveFile) {
      file = options.serveFile(req.body.filename)
    } else {
      file.filePath = options.filePath;
    }

    fs.readFile(options.minisignSecretKeyFilePath, (err, secretKeyBuffer) => {
      if (err) {
        res.sendStatus(500);
      } else {
        const bufferedPassword = Buffer.from(options.minisignPassword);
        const parsedSecretKey = minisign.parseSecretKey(secretKeyBuffer);
        let password = sodium.sodium_malloc(bufferedPassword.byteLength);
        password.fill(bufferedPassword);
        const secretKeyInfo = minisign.extractSecretKey(password, parsedSecretKey);
        fs.readFile(file.filePath, (err, fileContent) => {
          if (err) {
            res.sendStatus(500);
          } else {
            const signedDetails = minisign.signContent(fileContent, secretKeyInfo, options.signContentOptions);
            const base64Signature = signedDetails.outputBuf.toString('base64');
            res.set('x-file-minisign-signature', base64Signature);
            res.attachment(file.filePath);
            res.status(200);
            res.sendFile(file.filePath, options.sendFileOptions);
          }
        });
      }
    });
  }
}
