"use strict";

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

const createTransport = require('nodemailer').createTransport;

const transporter = createTransport({
  host: 'ketrenos.com',
  pool: true,
  port: 25
});

const templates = {
  "verify": {
    "html": [
      "<p>Hello {{firstName}},</p>",
      "",
      "<p>Welcome to <b>goodtimes.ketrenos.com</b>. You are almost done creating your account. ",
      "Before you can access the system, you must verify your email address {{email}}.</p>",
      "",
      "<p>To do so, simply access this link:</p>",
      "<p><a href=\"{{url}}{{secret}}\">VERIFY ADDRESS</a></p>",
      "",
      "<p>Sincerely,</p>",
      "<p>James</p>"
    ].join("\n"),
    "text": [
      "Hello {{firstName}},",
      "",
      "Welcome to goodtimes.ketrenos.com. You are almost done creating your account. ",
      "Before you can access the system, you must verify your email address {{email}}.",
      "",
      "To do so, simply access this link:",
      "",
      "{{url}}{{secret}}",
      "",
      "Sincerely,",
      "James"
    ].join("\n")
  }, 
  "verified": {
    "html": [
      "<p>The user {{email}} verified their address and is now active",
      "on Goodtimes.</p>",
      "",
      "<p>Sincerely,</p>",
      "<p>James</p>"
    ].join("\n"),
    "text": [
       "The user {{email}} verified their address and is now active",
       "on Goodtimes.",
      "",
      "Sincerely,",
      "James"
    ].join("\n")
  }, 
  "password": {
    "html": [
      "<p>Hello {{firstName}},</p>",
      "",
      "<p>You changed your password on <b>goodtimes.ketrenos.com</b>.</p>",
      "",
      "<p>Sincerely,</p>",
      "<p>James</p>"
    ].join("\n"),
    "text": [
      "Hello {{firstName}},",
      "",
      "You changed your password on goodtimes.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) {
    if (!transporter) {
      console.log("Not sending VERIFY email; SMTP not configured.");
      return;
    }

    let data = {
      firstName: user.firstName,
      email: user.email,
      secret: secret,
      url: req.protocol + "://" + req.hostname + req.app.get("basePath") +
        "user/verify-email/"
    }, envelope = {
      to: data.email,
      from: config.get("smtp.sender"),
      subject: "Request to goodtimes.ketrenos.com create account for '" + data.firstName + "'",
      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 email. 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) {
  if (!transporter) {
    console.log("Not sending VERIFY email; SMTP not configured.");
    return;
  }

  let data = {
    firstName: user.firstName,
    email: user.email,
    url: req.protocol + "://" + req.hostname + req.app.get("basePath")
  }, envelope = {
    to: data.email,
    from: config.get("smtp.sender"),
    subject: "Password changed on goodtimes.ketrenos.com for '" + data.firstName + "'",
    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 email. Trying again in 100ms (" + attempts + " attempts remain): ", error);
        setTimeout(send.bind(undefined, envelope), 100);
      });
    }

    send(envelope);
  });
};

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

 const envelope = {
    to: config.get("admin.mail"),
    from: config.get("smtp.sender"),
    subject: "VERIFIED: Account '" + user.email + "'",
    cc: "",
    bcc: "",
    text: hb.compile(templates.verified.text)(user),
    html: hb.compile(templates.verified.html)(user)
  };

  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,
  sendVerifiedMail,
  sendPasswordChangedMail
}
