text: 'use strict'
  
  var rootDir = process.cwd()
  var bcrypt = require('bcrypt')
  var xkcd = require('xkcd-pwgen')
  var winston = require('winston')
  var config = require(rootDir + '/app/config')
  var accountHelpers = require(rootDir + '/server/utils/account-helpers')
  var emailUtil = require(rootDir + '/server/utils/email')
  var EMAIL_TO = config.get('EMAIL_TO')
  var _countdown = 10
  var singleHtml
  
  var html = ''
  
  html += '<h2>Password reminder for #{firstName}</h2>'
  html += '<p style="color:red;">Someone is requesting access to your account.'
  html += 'If you did not request this information, you can ignore and delete this email.</p>'
  html += '<p>Your username is: &ldquo;<strong>#{email}</strong>&rdquo; ✔</p>'
  html += '<p>Your password is: &ldquo;<strong>#{password}</strong>&rdquo; ✔</p>'
  
  exports.actions = function (req, res, ss) {
    req.use('session')
  
    var UserModel = ss.service.db.model('User')
    var GameModel = ss.service.db.model('Game')
  
    var _setUserSession = function (user) {
      req.session.setUserId(user.id)
      req.session.firstName = user.firstName
      req.session.lastName = user.lastName
      req.session.email = user.email
      req.session.role = user.role
      req.session.game = user.game
      req.session.gameStarted = user.gameStarted
      req.session.profileSetup = user.profileSetup
      req.session.profileLink = user.profileLink
      req.session.channel.subscribe(user.game.instanceName)
      req.session.save()
      return {
        id: req.session.userId,
        firstName: req.session.firstName,
        lastName: req.session.lastName,
        email: req.session.email,
        role: req.session.role,
        game: req.session.game,
        gameStarted: req.session.gameStarted,
        profileSetup: req.session.profileSetup,
        profileLink: req.session.profileLink
      }
    }
  
    var dbHelpers = {
      checkGameActive: function (instance, callback) {
        GameModel
          .where('instanceName').equals(instance)
          .findOne(function (err, game) {
            if (err) {
              callback(false)
            } else {
              callback(game.active)
            }
          })
      }
    }
  
    return {
  
      authenticate: function (email, password) {
        winston.info('Checking authentication for ', email)
        UserModel.findOne({ email: email }, function (err, user) {
          if (err) {
            // Placeholder for error handling
          } else if (user) {
            bcrypt.compare(password, user.password, function (err, authenticated) {
              if (err) {
                // Placeholder for error handling
              } else if (authenticated) {
                res({ status: true, session: _setUserSession(user) })
              } else {
                res({ status: false, reason: 'Incorrect password.' })
              }
            })
          } else {
            res({ status: false, reason: 'No user exists with that email.' })
          }
        })
      },
  
      deAuthenticate: function () {
        winston.info('Deauthenticating...')
        // console.log(req.session.firstName, req.session.email, req.session.role, req.session.gameChannel, req.session.userId);
  
        var sessionId = req.sessionId
        var sessionEmail = req.session.email
  
        // MONGO
        UserModel.findOne({ email: sessionEmail }, function (err, user) {
          if (err) {
            // Placeholder for error handling
          } else if (user && user.activeSessionID && user.activeSessionID === sessionId) {
            // req.session.activeSessionID = null;
            // req.session.save();
            user.set({ activeSessionID: null })
            user.save(function (error) {
              if (error) {
                console.log('Error making active session ID null in mongodb'.red)
              } else {
                console.log('Active session ID made null in mongodb'.green)
              }
            })
          }
        })
  
        // REDIS
        // NOTE: these cannot depend on each other: REDIS and MONGO deletions have to be independent
        req.session.setUserId(null)
        req.session.save(function(error) {
          if (error) {
            console.error('User session destroy failed!'.red)
            res({ status: false, reason: error })
          } else {
            // console.error('User session destroyed!'.red)
            // console.log(req.session.firstName, req.session.email, req.session.role, req.session.gameChannel, req.session.userId);
            req.session.channel.reset()
            res({ status: true, reason: 'Session destroyed.' })
          }
        })
      },
  
      getUserSession: function () {
        if (req.session.userId) {
          res({
            id: req.session.userId,
            firstName: req.session.firstName,
            lastName: req.session.lastName,
            email: req.session.email,
            role: req.session.role,
            game: req.session.game,
            gameStarted: req.session.gameStarted,
            profileSetup: req.session.profileSetup,
            profileLink: req.session.profileLink
          })
        } else {
          res('NOT_AUTHENTICATED')
        }
      },
  
      checkGameSession: function () {
        dbHelpers.checkGameActive(req.session.game.instanceName, function (active) {
          if (active) {
            UserModel.findById(req.session.userId, function (error, user) {
              if (error || !user) {
                console.error('Error finding user (game) session in Mongo.'.red)
                res({
                  status: false,
                  reason: error
                })
              } else {
                if (user.activeSessionID) {
                  console.log(user.activeSessionID, req.sessionId)
  
                  if (user.activeSessionID === req.sessionId) {
                    // NOTE: this is sort of a weird scenario -- not sure it's even needed to check it!
                    console.log('Active session matches session ID -- good to go!'.green)
                    res({ status: true })
                  } else {
                    console.error('Active session ID does not match session ID.'.red)
                    res({ status: false })
                    ss.publish.user(user.id, 'verifyGameStatus', {
                      countdown: _countdown,
                      userId: user.id,
                      profileLink: user.profileLink
                    })
                  }
                } else {
                  console.log('No active session ID.')
                  // req.session.activeSessionID = req.sessionId;
                  // req.session.save();
                  // make sure to save the active session to mongodb, so we can look it up again
                  user.set({ activeSessionID: req.sessionId })
                  user.save(function (error) {
                    if (error) {
                      console.error('Error saving active session ID to mongodb'.red)
                      res({
                        status: false,
                        reason: error,
                        profileLink: user.profileLink
                      })
                    } else {
                      console.log('Active session ID saved to mongodb'.green)
                      res({ status: true })
                    }
                  })
                }
              }
            })
          } else {
            console.log('Game inactive')
            res({ status: false })
            ss.publish.user(req.session.userId, 'inactiveGameRedirect', {
              profileLink: req.session.profileLink
            })
          }
        })
      },
  
      denyNewSession: function (req) {
        ss.publish.user(req.userId, 'denyNewSession', req)
      },
  
      approveNewSession: function (userId) {
        ss.publish.user(userId, 'approveNewSession', userId)
      },
  
      setActiveSessionId: function (userId) {
        UserModel.findById(userId, function (error, user) {
          if (error) {
            console.error('Error finding user in Mongo.'.red)
          } else {
            // req.session.activeSessionID = req.sessionId;
            // req.session.save();
            user.set({ activeSessionID: req.sessionId })
            user.save(function (error) {
              if (error) {
                console.error('Error saving active session ID to mongodb'.red)
              } else {
                console.log('Saved a new activeSessionID'.green)
              }
            })
          }
        })
      },
  
      remindMeMyPassword: function (email) {
        UserModel.findOne({ email: email }, function (err, user) {
          if (!err && user) {
            // TODO THIS AUTO RESETS without creds!!
            var password = xkcd.generatePassword()
            accountHelpers.hashPassword(password, function (hashedPassword) {
              user.password = hashedPassword.hash
  
              singleHtml = html.replace('#{firstName}', user.firstName)
              singleHtml = singleHtml.replace('#{email}', user.email)
              singleHtml = singleHtml.replace('#{password}', password)
  
              user.save(function (err) {
                if (err) {
                  res(false)
                } else {
                  emailUtil.sendEmail('Password reset from Civic Seed', singleHtml, user.email, function (err, response) {
                    if (err) {
                      res(false)
                    } else {
                      res(true)
                    }
                  })
                }
              })
            })
          } else {
            res(false)
          }
        })
      },
  
      sendMessage: function (email, message) {
        var messageHTML = ''
  
        messageHTML += '<h2>Civic Seed contact form submission</h2>'
        messageHTML += '<p><strong>E-mail:</strong> ' + email + '</p>'
        messageHTML += '<p><strong>Message:</strong> ' + message + '</p>'
  
        emailUtil.sendEmail('Civic Seed contact form submission', messageHTML, EMAIL_TO, function (err, response) {
          if (err) {
            res(false)
          } else {
            res(true)
          }
        })
      },
  
      changeInfo: function (info) {
        UserModel.findOne({ email: req.session.email }, function (err, user) {
          if (!err && user) {
            user.set({
              firstName: info.first,
              lastName: info.last,
              school: info.school,
              profileSetup: true
            })
            user.save(function (err, suc) {
              if (!err && suc) {
                req.session.firstName = info.first
                req.session.lastName = info.last
                req.session.save()
                res({firstName: info.first, lastName: info.last})
              } else {
                res(false)
              }
            })
          } else {
            res(false)
          }
        })
      },
  
      startGame: function () {
        UserModel.findOne({ email: req.session.email }, function (err, user) {
          if (err) {
            // Placeholder for error handling
          } else if (user) {
            user.set({
              gameStarted: true
            })
            user.save(function (err, suc) {
              if (err) {
                // Placeholder for error handling
              } else {
                res(true)
              }
            })
          }
        })
      }
  
    }
  }
  