/*
  Used to abstract away the Queue system used.  It uses the Bull queue system
  internally, which uses Redis as a queue.  This works fine but if you wanted
  to use something else you'd need to rewrite this file and maintain the data
  formats sent.

  The point of using a Queue is to take processing that might take a while and
  push it to a separate process.  For example, after a user has paid you may
  need to run complicated PDF libraries to craft their receipt.  You don't want
  to do that _inside_ your `api/` handler as that will slow down the response.
  The PDF/receipt also isn't something they need to know about immediately, so
  just shove that into a queue a queue and let another process (or multiple
  processes) do it.

  A good pattern is to create your `api/` handler so that it works, then identify
  any code that could be placed in a queue job, then move that code into a
  queue handler in `queues/`.  The ideal situation is where your `api/` handler
  does nothing but send a message to a queue.  If the operation the user requested
  doesn't need immediate feedback, then consider using a queue and sending them
  an email when it's done.
 */
import Queue from 'bull';

/*
  Create a new Queue with the given name.  Mostly used internally but
  you if you need to use the queue system in your own code then this
  how you do it.

  ___BUG___: I'm not clear on the semantics of the bull queues.  Should I make
  one per process and use it in all functions?  Or, make one for every
  place I need it and don't share them?

  + `name string` -- Name for the queue.
  + ___return___ `Queue` object to use.
 */
export const create = (name) => {
  return new Queue(name);
}

/*
  Sends a `mail/registration` message to the queue that handles mail. See `queues/mail.js`
  for how the sending actually works.

  ___WARNING__:  This doesn't restrict what can go in the queue, and it's possible Bull isn't
  that good at clearing the queue of records, so user information may be leaked into redis.

  + `user User` -- The `User` object should be ready to use by the quee in `queues/mail.js`.
 */
export const send_registration = (user) => {
  const mail = create("mail/registration");
  mail.add({user});
}

/*
  Sends the welcome email to a user.  Look in `queues/mail.js` to see how this is really done.

  ___WARNING__:  This doesn't restrict what can go in the queue, and it's possible Bull isn't
  that good at clearing the queue of records, so user information may be leaked into redis.

  + `user User` -- The `User` object should be ready to use by the quee in `queues/mail.js`.
 */
export const send_welcome = (user) => {
  const mail = create("mail/welcome");
  mail.add({user});
}

/*
  Sends a receipt request to the queue process.  Receipt processing can get insanely complicated
  depending on what the user needs.  I tend to use simple HTML email, but if you want to get
  into pointless PDF receipts then definitely use a queue handler.

  ___WARNING__:  This doesn't restrict what can go in the queue, and it's possible Bull isn't
  that good at clearing the queue of records, so user information may be leaked into redis.

  + `user User` -- The `User` object should be ready to use by the quee in `queues/mail.js`.
  + `payment_id number` -- The `id` for the payment to attach to the receipt.
  + `product_id number` -- The `Product` they purchased.
 */
export const send_receipt = (user, payment_id, product_id) => {
  const mail = create("mail/receipt");
  mail.add({user, payment_id, product_id});
}

/*
  Sends a password reset __REQUEST__ email.  This doesn't do the reset, only give them
  the code to their email for the reset.  One thing this does is include the IP address
  and browser User Agent so the receiver will know if they requested it or not.  The security
  mechanism to prevent repeated reset attempts is:

  + There's a max limit on requests in `api/password_reset.js:RESET_MAX`.
  + There's an enforced delay on requests of 1 per 10 hours in `api/password_reset.js:RESET_HOURS_MAX`.
  + The user's email is notified of the IP address and browser used on request _and_ reset complete.
  + The account is locked if `RESET_MAX` is reached and no more attempts are accepted.

  With this an attacker would get one guess every 10 hours, the user would be notified of the attempt (giving them time to notify admins), and if the attacker makes > `RESET_MAX` attempts the account is locked.

  ___WARNING__:  This doesn't restrict what can go in the queue, and it's possible Bull isn't
  that good at clearing the queue of records, so user information may be leaked into redis.

  + `user User` -- The `User` object should be ready to use by the queue in `queues/mail.js`.
  + `ip_address string` -- The IP address of the computer requesting the reset.
  + `browser string` -- The user agent of the browser requesting.
 */
export const send_reset = (user, ip_address, browser) => {
  const mail = create("mail/reset");
  mail.add({user, ip_address, browser});
}

/*
  Send the final notification that the reset was successful.  See `send_reset` for more
  security rules.

  ___WARNING__:  This doesn't restrict what can go in the queue, and it's possible Bull isn't
  that good at clearing the queue of records, so user information may be leaked into redis.

  + `user User` -- The `User` object should be ready to use by the queue in `queues/mail.js`.
  + `ip_address string` -- The IP address of the computer requesting the reset.
  + `browser string` -- The user agent of the browser requesting.
*/
export const send_reset_finished = (user, ip_address, browser) => {
  const mail = create("mail/reset_finished");
  mail.add({user, ip_address, browser});
}

/*
  Used to quickly update the current view statistics on `Livestream` to all
  users viewing it.  Since this isn't crucial and not something a user expects
  to be updated immediately it's easy to shove it into a queue.  The queue handler
  in `queues/live.js` will use `sockets/live.js` to send out an announce.

  + `api_key string` -- Used to make sure this is from the server. Users shouldn't see this.
 */
export const send_update_viewers = (api_key) => {
  const live = create("live/update_viewers");
  live.add({api_key});
}

/*
  Adds to a `Livesteam` view count in the database for statistics.

  + `livestream_id number` -- The `id` of the `Livestream` to update.
 */
export const add_view_count = (livestream_id) => {
  const live = create("live/add_view_count");
  live.add({livestream_id});
}

export default {
  create, send_welcome, send_reset, send_reset_finished, send_update_viewers
}
