var r = require('rethinkdb')

var db = require('./')
var wireutil = require('../wire/util')

var dbapi = Object.create(null)

dbapi.close = function(options) {
  return db.close(options)
}

dbapi.saveUserAfterLogin = function(user) {
  return db.run(r.table('users').get(user.email).update({
      name: user.name
    , ip: user.ip
    , lastLoggedInAt: r.now()
    }))
    .then(function(stats) {
      if (stats.skipped) {
        return db.run(r.table('users').insert({
          email: user.email
        , name: user.name
        , ip: user.ip
        , group: wireutil.makePrivateChannel()
        , lastLoggedInAt: r.now()
        , createdAt: r.now()
        , forwards: []
        }))
      }
      return stats
    })
}

dbapi.loadUser = function(email) {
  return db.run(r.table('users').get(email))
}

dbapi.addUserForward = function(email, forward) {
  var devicePort = forward.devicePort
  return db.run(r.table('users').get(email).update({
    forwards: r.row('forwards').default([]).filter(function(forward) {
      return forward('devicePort').ne(devicePort)
    }).append(forward)
  }))
}

dbapi.removeUserForward = function(email, devicePort) {
  return db.run(r.table('users').get(email).update({
    forwards: r.row('forwards').default([]).filter(function(forward) {
      return forward('devicePort').ne(devicePort)
    })
  }))
}

dbapi.loadGroup = function(email) {
  return db.run(r.table('devices').getAll(email, {
    index: 'owner'
  }))
}

dbapi.saveDeviceLog = function(serial, entry) {
  return db.run(r.table('logs').insert({
      serial: entry.serial
    , timestamp: r.epochTime(entry.timestamp)
    , priority: entry.priority
    , tag: entry.tag
    , pid: entry.pid
    , message: entry.message
    }
  , {
      durability: 'soft'
    }))
}

dbapi.saveDevice = function(serial, device) {
  var data = {
    present: true
  , provider: device.provider
  , owner: null
  , status: device.status
  , ready: false
  , statusChangedAt: r.now()
  , createdAt: r.now()
  , lastHeartbeatAt: r.now()
  }
  return db.run(r.table('devices').get(serial).update(data))
    .then(function(stats) {
      if (stats.skipped) {
        data.serial = serial
        return db.run(r.table('devices').insert(data))
      }
      return stats
    })
}

dbapi.saveDeviceStatus = function(serial, status) {
  return db.run(r.table('devices').get(serial).update({
    status: status
  , statusChangedAt: r.now()
  }))
}

dbapi.setDeviceOwner = function(serial, owner) {
  return db.run(r.table('devices').get(serial).update({
    owner: owner
  }))
}

dbapi.unsetDeviceOwner = function(serial) {
  return db.run(r.table('devices').get(serial).update({
    owner: null
  }))
}

dbapi.setDeviceAbsent = function(serial) {
  return db.run(r.table('devices').get(serial).update({
    present: false
  , ready: false
  , lastHeartbeatAt: null
  }))
}

dbapi.setDeviceAirplaneMode = function(serial, enabled) {
  return db.run(r.table('devices').get(serial).update({
    airplaneMode: enabled
  }))
}

dbapi.setDeviceBattery = function(serial, battery) {
  return db.run(r.table('devices').get(serial).update({
    battery: {
      status: battery.status
    , health: battery.health
    , source: battery.source
    , level: battery.level
    , scale: battery.scale
    , temp: battery.temp
    , voltage: battery.voltage
    }
  }))
}

dbapi.setDeviceBrowser = function(serial, browser) {
  return db.run(r.table('devices').get(serial).update({
    browser: {
      selected: browser.selected
    , apps: browser.apps
    }
  }))
}

dbapi.setDeviceConnectivity = function(serial, connectivity) {
  return db.run(r.table('devices').get(serial).update({
    network: {
      connected: connectivity.connected
    , type: connectivity.type
    , subtype: connectivity.subtype
    , failover: !!connectivity.failover
    , roaming: !!connectivity.roaming
    }
  }))
}

dbapi.setDevicePhoneState = function(serial, state) {
  return db.run(r.table('devices').get(serial).update({
    network: {
      state: state.state
    , manual: state.manual
    , operator: state.operator
    }
  }))
}

dbapi.setDeviceRotation = function(serial, rotation) {
  return db.run(r.table('devices').get(serial).update({
    display: {
      orientation: rotation
    }
  }))
}

dbapi.setDeviceChannel = function(serial, channel) {
  return db.run(r.table('devices').get(serial).update({
    channel: channel
  }))
}

dbapi.saveDeviceIdentity = function(serial, identity) {
  return db.run(r.table('devices').get(serial).update({
    ready: true
  , platform: identity.platform
  , manufacturer: identity.manufacturer
  , operator: identity.operator
  , model: identity.model
  , version: identity.version
  , abi: identity.abi
  , sdk: identity.sdk
  , display: identity.display
  , phone: identity.phone
  }))
}

dbapi.loadDevices = function() {
  return db.run(r.table('devices'))
}

dbapi.loadDevice = function(serial) {
  return db.run(r.table('devices').get(serial))
}

dbapi.updateProviderHeartbeat = function(channel) {
  return db.run(
    r.table('devices').getAll(channel, {
        index: 'providerChannel'
      })
      .update({
        lastHeartbeatAt: r.now()
      })
  , {
      noreply: true
    , durability: 'soft'
    }
  )
}

dbapi.getDeadDevices = function(timeout) {
  return db.run(
    r.table('devices')
      .between(null, r.now().sub(timeout / 1000), {
        index: 'lastHeartbeatAt'
      })
      .pluck('serial')
  )
}

module.exports = dbapi
