import {EventEmitter} from 'events'
import {lookupPretty} from 'ipfs-geoip'

export default class StatsPoller extends EventEmitter {
  constructor (ipfs, logger) {
    super()
    this.ipfs = ipfs
    this.logger = logger
    this.shouldPoll = false
    this.statsCache = {}
    this.locationsCache = {}
  }

  _poller () {
    const next = () => setTimeout(() => this._poller(), 1000)

    if (!this.shouldPoll) {
      return
    }

    this.ipfs.swarm.peers()
      .then((res) => {
        res = res.sort((a, b) => a.peer.toB58String() > b.peer.toB58String())

        let peers = []

        res.forEach((rawPeer) => {
          let peer = {
            id: rawPeer.peer.toB58String(),
            addr: rawPeer.addr.toString(),
            location: {
              formatted: 'Unknown'
            }
          }

          if (!this.locationsCache[peer.id]) {
            lookupPretty(this.ipfs, [peer.addr], (err, result) => {
              if (err) { return }
              this.locationsCache[peer.id] = result
            })
          } else {
            peer.location = this.locationsCache[peer.id]
          }

          peers.push(peer)
        })

        this.statsCache.peers = peers
        this.emit('change', this.statsCache)
      }, this.logger.error)
      .then(next)

    this.ipfs.id()
      .then((peer) => {
        this.statsCache.node = peer
        this.statsCache.node.location = 'Unknown'

        lookupPretty(this.ipfs, peer.addresses, (err, location) => {
          if (err) { return }

          this.statsCache.node.location = location && location.formatted
          this.emit('change', this.statsCache)
        })
      })
      .catch(this.logger.error)

    this.ipfs.stats.bw()
      .then(stats => {
        this.statsCache.bw = stats
        this.emit('change', this.statsCache)
      })
      .catch(this.logger.error)

    this.ipfs.repo.stat()
      .then(repo => {
        this.statsCache.repo = repo
        this.emit('change', this.statsCache)
      })
      .catch(this.logger.error)
  }

  stop () {
    this.shouldPoll = false
  }

  start () {
    this.shouldPoll = true
    this._poller()
  }
}

import {EventEmitter} from 'events'
import {lookupPretty} from 'ipfs-geoip'

export default class StatsPoller extends EventEmitter {
  constructor (ipfs, logger) {
    super()
    this.ipfs = ipfs
    this.logger = logger
    this.shouldPoll = false
    this.statsCache = {}
    this.locationsCache = {}
  }

  _poller () {
    if (!this.shouldPoll) {
      return
    }

    Promise.all([
      this.ipfs.id(),
      this.ipfs.swarm.peers(),
      this.ipfs.stats.bw(),
      this.ipfs.repo.stat()
    ]).then(([id, peers, bw, repo]) => {
      this.statsCache.bw = bw
      this.statsCache.repo = repo
      this._handleId(id)
      this._handlePeers(peers)

      this.emit('change', this.statsCache)

      setTimeout(() => {
        this._poller()
      }, 1000)
    }).catch(this.logger.error)
  }

  _handlePeers (raw) {
    const peers = []
    raw = raw.sort((a, b) => a.peer.toB58String() > b.peer.toB58String())

    raw.forEach((rawPeer) => {
      let peer = {
        id: rawPeer.peer.toB58String(),
        addr: rawPeer.addr.toString(),
        location: {
          formatted: 'Unknown'
        }
      }

      if (!this.locationsCache[peer.id]) {
        lookupPretty(this.ipfs, [peer.addr], (err, result) => {
          if (err) { return }
          this.locationsCache[peer.id] = result
        })
      } else {
        peer.location = this.locationsCache[peer.id]
      }

      peers.push(peer)
    })

    this.statsCache.peers = peers
    this.emit('change', this.statsCache)
  }

  _handleId (raw) {
    this.statsCache.node = raw
    this.statsCache.node.location = 'Unknown'

    lookupPretty(this.ipfs, raw.addresses, (err, location) => {
      if (err) { return }

      this.statsCache.node.location = location && location.formatted
      this.emit('change', this.statsCache)
    })
  }

  stop () {
    this.shouldPoll = false
  }

  start () {
    this.shouldPoll = true
    this._poller()
  }
}

improve and simplify poller