module.exports = function DeviceListStatsDirective(
  UserService
) {
  return {
    restrict: 'E'
  , template: require('./device-list-stats.jade')
  , scope: {
      tracker: '&tracker'
    }
  , link: function (scope, element) {
      var tracker = scope.tracker()
        , mapping = Object.create(null)
        , nodes = Object.create(null)

      scope.counter = {
        total: 0
      , usable: 0
      , busy: 0
      , using: 0
      }

      scope.currentUser = UserService.currentUser

      function findTextNodes() {
        var elements = element[0].getElementsByClassName('counter')
        for (var i = 0, l = elements.length; i < l; ++i) {
          nodes[elements[i].getAttribute('data-type')] = elements[i].firstChild
        }
      }

      function notify() {
        nodes.total.nodeValue = scope.counter.total
        nodes.usable.nodeValue = scope.counter.usable
        nodes.busy.nodeValue = scope.counter.busy
        nodes.using.nodeValue = scope.counter.using
      }

      function updateStats(device) {
        return (mapping[device.serial] = {
          usable: device.usable ? 1 : 0
        , busy: device.owner ? 1 : 0
        , using: device.using ? 1 : 0
        })
      }

      function addListener(device) {
        var stats = updateStats(device)

        scope.counter.total += 1
        scope.counter.usable += stats.usable
        scope.counter.busy += stats.busy
        scope.counter.using += stats.using

        notify()
      }

      function changeListener(device) {
        var oldStats = mapping[device.serial]
          , newStats = updateStats(device)
          , diffs = Object.create(null)

        scope.counter.usable += diffs.usable = newStats.usable - oldStats.usable
        scope.counter.busy += diffs.busy = newStats.busy - oldStats.busy
        scope.counter.using += diffs.using = newStats.using - oldStats.using

        if (diffs.usable || diffs.busy || diffs.using) {
          notify()
        }
      }

      function removeListener(device) {
        var oldStats = mapping[device.serial]
          , newStats = updateStats(device)

        scope.counter.total -= 1
        scope.counter.busy += newStats.busy - oldStats.busy
        scope.counter.using += newStats.using - oldStats.using

        delete mapping[device.serial]

        notify()
      }

      findTextNodes()

      tracker.on('add', addListener)
      tracker.on('change', changeListener)
      tracker.on('remove', removeListener)

      scope.$on('$destroy', function() {
        tracker.removeListener('add', addListener)
        tracker.removeListener('change', changeListener)
        tracker.removeListener('remove', removeListener)
      })
    }
  }
}
