const path = require('path')
const crypto = require('crypto')
const express = require('express')
const bodyParser = require('body-parser')
const jsonResponse = require('q-json-response')
const auth = require(path.join(path.dirname(require.main.filename), '../lib/game/api/auth'))
const authlib = require(path.join(path.dirname(require.main.filename), '../lib/authlib'))
const _ = require('lodash')

module.exports = function (config) {
  const { common } = config
  const { db, env, pubsub } = common.storage
  const router = new express.Router()
  config.backend.on('expressPreConfig', (app) => app.use(router))
  router.use(bodyParser.json({
    limit: '8mb',
    verify (request, response, buf, encoding) {
      request.rawBody = buf.toString(encoding)
    }
  }))
  router.post('/api/game/add-object-intent', auth.tokenAuth, jsonResponse((request) => {
    return checkGame(request)
      .then(() => {
        if (request.body.name === 'activateSafeMode') {
          return common.getGametime()
            .then(gameTime => db['rooms.objects'].count({$and: [{type: 'controller'}, {user: '' + request.user._id}, {safeMode: {$gt: gameTime}}]}))
            .then(count => count > 0 ? Promise.reject(new Error('safe mode active already')) : undefined)
        }
      })
      .then(() => env.hmset(env.keys.ROOM_INTENTS + request.body.room, request.user._id.toString() + '.manual', JSON.stringify({[request.body._id]: { [request.body.name]: request.body.intent }})))
      .then(() => db.rooms.update({ _id: request.body.room }, {$set: { active: true }}))
  }))
  router.get('/api/user/messages/index', auth.tokenAuth, jsonResponse((request) => {
    return db['users.messages'].findEx({user: request.user._id}, {sort: {date: -1}})
      .then(data => {
        var messages = []
        data.forEach(message => {
          if (!messages.find(i => i._id === message.respondent)) {
            messages.push({_id: message.respondent, message})
          }
        })
        return db.users.find({_id: {$in: _.map(messages, '_id')}})
          .then(users => {
            users = users.map(i => _.pick(i, ['_id', 'username', 'badge']))
            return {messages, users: _.indexBy(users, '_id')}
          })
      })
  }))
  router.post('/api/user/messages/mark-read', auth.tokenAuth, jsonResponse((request) => {
    var _id = request.body.id
    var message
    return db['users.messages'].findOne({_id, user: request.user._id, type: 'in'})
      .then((_message) => {
        if (!_message) {
          return Promise.reject(new Error('invalid id'))
        }
        message = _message
        return db['users.messages'].update({_id}, {$set: {unread: false}})
      })
      .then((data) => {
        return Promise.all([
          pubsub.publish(`user:${message.user}/message:${message.respondent}`, JSON.stringify({message: {
            _id: request.body.id,
            unread: false
          }})),
          pubsub.publish(`user:${message.respondent}/message:${message.user}`, JSON.stringify({message: {
            _id: message.outMessage,
            unread: false
          }})),
          db['users.messages'].update({_id: message.outMessage}, {$set: {unread: false}})
        ])
      })
  }))
  authlib.genToken = function (id) {
    const token = crypto.createHmac('sha1', 'hsdhweh342sdbj34e').update(new Date().getTime() + id).digest('hex')
    return env.setex(`auth_${token}`, 300, id).then(() => token)
  }

  authlib.checkToken = function (token, noConsume) {
    const authKey = `auth_${token}`

    return env.get(authKey)
      .then((data) => {
        if (!data) {
          return Promise.reject(false) // eslint-disable-line prefer-promise-reject-errors
        }
        if (!noConsume) {
          env.ttl(authKey)
            .then((ttl) => {
              if (ttl > 300) {
                env.expire(authKey, 300)
              }
            })
        }
        return db.users.findOne({_id: data})
      })
      .then((user) => {
        if (!user) {
          return Promise.reject(false) // eslint-disable-line prefer-promise-reject-errors
        }
        env.set(env.keys.USER_ONLINE + user._id, Date.now())
        return user
      })
  }

  function checkGame (req) {
    return db.rooms.findOne({ _id: req.body.room })
      .then((room) => {
        if (!room) {
          return Promise.reject(new Error('invalid room'))
        }
        if (/^(W|E)/.test(req.body.room)) {
          if (room.status === 'out of borders' || (room.openTime && room.openTime > Date.now())) {
            return Promise.reject(new Error('out of borders'))
          }
          return true
        }
        return Promise.reject(new Error('not supported'))
      })
  }
}

@@ -478,16 +478,8 @@
  env
-, pubsub
  %7D =
@@ -1725,24 +1725,26 @@
 -1%7D%7D)%0A      
+  
 .then(data =
@@ -1743,24 +1743,26 @@
 n(data =%3E %7B%0A
+  
         var 
@@ -1783,16 +1783,18 @@
         
+  
 data.for
@@ -1807,24 +1807,26 @@
 essage =%3E %7B%0A
+  
           if
@@ -1888,24 +1888,26 @@
             
+  
 messages.pus
@@ -1946,34 +1946,38 @@
 age%7D)%0A          
-%7D%0A
+  %7D%0A  
         %7D)%0A     
@@ -1963,32 +1963,34 @@
  %7D%0A          %7D)%0A
+  
         return d
@@ -2046,24 +2046,30 @@
 )%0A          
+      
 .then(users 
@@ -2069,24 +2069,30 @@
 (users =%3E %7B%0A
+      
             
@@ -2171,1057 +2171,83 @@
     
-return %7Bmessages, users: _.indexBy(users, '_id')%7D%0A          %7D)%0A      %7D)%0A  %7D))%0A  router.post('/api/user/messages/mark-read', auth.tokenAuth, jsonResponse((request) =%3E %7B%0A    var _id = request.body.id%0A    var message%0A    return db%5B'users.messages'%5D.findOne(%7B_id, user: request.user._id, type: 'in'%7D)%0A      .then((_message) =%3E %7B%0A        if (!_message) %7B%0A          return Promise.reject(new Error('invalid id'))%0A        %7D%0A        message = _message%0A        return db%5B'users.messages'%5D.update(%7B_id%7D, %7B$set: %7Bunread: false%7D%7D)%0A      %7D)%0A      .then((data) =%3E %7B%0A        return Promise.all(%5B%0A          pubsub.publish(%60user:$%7Bmessage.user%7D/message:$%7Bmessage.respondent%7D%60, JSON.stringify(%7Bmessage: %7B%0A            _id: request.body.id,%0A            unread: false%0A          %7D%7D)),%0A          pubsub.publish(%60user:$%7Bmessage.respondent%7D/message:$%7Bmessage.user%7D%60, JSON.stringify(%7Bmessage: %7B%0A            _id: message.outMessage,%0A            unread: false%0A          %7D%7D)),%0A          db%5B'users.messages'%5D.update(%7B_id: message.outMessage%7D, %7B$set: %7Bunread: false%7D%7D)%0A        %5D)%0A
+      return %7Bmessages, users: _.keyBy(users, '_id')%7D%0A                %7D)%0A  
     

Revert "fixes opening user messages in the game client"