"use strict";

const config = require("config"),
  crypto = require("crypto"),
  hb = require("handlebars");

const templates = {
  "verify": {
    "html": [
      "<p>Hello {{username}},</p>",
      "",
      "<p>Welcome to <b>ketrenos.com</b>. You are almost done creating your account. ",
      "Before you can access the system, you must verify your email address.</p>",
      "",
      "<p>To do so, simply access this link:</p>",
      "<p><a href=\"{{url}}{{secret}}\">VERIFY {{mail}} ADDRESS</a></p>",
      "",
      "<p>Sincerely,</p>",
      "<p>James</p>"
    ].join("\n"),
    "text": [
      "Hello {{username}},",
      "",
      "Welcome to ketrenos.com. You are almost done creating your account. ",
      "Before you can access the system, you must verify your email address.",
      "",
      "To do so, simply access this link:",
      "",
      "{{url}}{{secret}}",
      "",
      "Sincerely,",
      "James"
    ].join("\n")
  }, 
  "password": {
    "html": [
      "<p>Hello {{username}},</p>",
      "",
      "<p>You changed your password on <b>ketrenos.com</b>.</p>",
      "",
      "<p>Sincerely,</p>",
      "<p>James</p>"
    ].join("\n"),
    "text": [
      "Hello {{username}},",
      "",
      "You changed your password on ketrenos.com.",
      "",
      "Sincerely,</p>",
      "James"
    ].join("\n")
  }
};

const sendVerifyMail = function(userDB, req, user) {
  return userDB.sequelize.query("DELETE FROM authentications WHERE userId=:id AND type='account-setup'", {
    replacements: {
      id: user.id
    }
  }).then(function() {
    return new Promise(function(resolve, reject) {
      crypto.randomBytes(16, function(error, buffer) {
        if (error) {
          return reject(error);
        }
        return resolve(buffer.toString('hex'));
      });
    });
  }).then(function(secret) {
    return userDB.sequelize.query(
      "INSERT INTO authentications " + 
      "(userId,issued,key,type) " +
      "VALUES (:userId,CURRENT_TIMESTAMP,:key,'account-setup')", {
      replacements: {
        key: secret,
        userId: user.id
      }
    }).then(function() {
      return secret;
    }).catch(function(error) {
      console.log(error);
      throw error;
    });
  }).then(function(secret) {
    const transporter = req.app.get("transporter");
    if (!transporter) {
      console.log("Not sending VERIFY email; SMTP not configured.");
      return;
    }

    let data = {
      username: user.displayName,
      mail: user.mail,
      secret: secret,
      url: req.protocol + "://" + req.hostname + req.app.get("basePath")
    }, envelope = {
      to: data.mail,
      from: config.get("smtp.sender"),
      subject: "Request to ketrenos.com create account for '" + data.username + "'",
      cc: "",
      bcc: config.get("admin.mail"),
      text: hb.compile(templates.verify.text)(data),
      html: hb.compile(templates.verify.html)(data)
    };
    return new Promise(function (resolve, reject) {
      let attempts = 10;
  
      function send(envelope) {
        /* Rate limit to ten per second */
        transporter.sendMail(envelope, function (error, info) {
          if (!error) {
            console.log('Message sent: ' + info.response);
            return resolve();
          }

          if (attempts == 0) {
            console.log("Error sending email: ", error);
            return reject(error);
          }
          
          attempts--;
          console.log("Unable to send mail. Trying again in 100ms (" + attempts + " attempts remain): ", error);
          setTimeout(send.bind(undefined, envelope), 100);
        });
      }

      send(envelope);
    });
  }).catch(function(error) {
    console.log("Error creating account: ", error);
  });
};

const sendPasswordChangedMail = function(userDB, req, user) {
  const transporter = req.app.get("transporter");
  if (!transporter) {
    console.log("Not sending VERIFY email; SMTP not configured.");
    return;
  }

  let data = {
    username: user.displayName,
    mail: user.mail,
    url: req.protocol + "://" + req.hostname + req.app.get("basePath")
  }, envelope = {
    to: data.mail,
    from: config.get("smtp.sender"),
    subject: "Password changed on ketrenos.com for '" + data.username + "'",
    cc: "",
    bcc: config.get("admin.mail"),
    text: hb.compile(templates.password.text)(data),
    html: hb.compile(templates.password.html)(data)
  };
  return new Promise(function (resolve, reject) {
    let attempts = 10;

    function send(envelope) {
      /* Rate limit to ten per second */
      transporter.sendMail(envelope, function (error, info) {
        if (!error) {
          console.log('Message sent: ' + info.response);
          return resolve();
        }

        if (attempts == 0) {
          console.log("Error sending email: ", error);
          return reject(error);
        }
        
        attempts--;
        console.log("Unable to send mail. Trying again in 100ms (" + attempts + " attempts remain): ", error);
        setTimeout(send.bind(undefined, envelope), 100);
      });
    }

    send(envelope);
  });
};

module.exports = {
  sendVerifyMail,
  sendPasswordChangedMail
}
