text: var stream = require('stream')
  var util = require('util')
  const clivas = require('clivas')
  
  var FileStream = function (engine, file, opts) {
    if (!(this instanceof FileStream)) return new FileStream(engine, file, opts)
    stream.Readable.call(this)
  
    if (!opts) opts = {}
    if (!opts.start) opts.start = 0
    if (!opts.end && typeof opts.end !== 'number') opts.end = file.length - 1
  
    var offset = opts.start + file.offset
    var pieceLength = engine.torrent.pieceLength
    this.length = opts.end - opts.start + 1
    clivas.clear()
    clivas.line('{yellow:file read:} ' + 'start:' + this.num2s(opts.start) + ' end:' + this.num2s(opts.end)  + ' len:' + this.num2s(this.length))
    clivas.line('')
    this.startPiece = (offset / pieceLength) | 0
    this.endPiece = ((opts.end + file.offset) / pieceLength) | 0
    this._destroyed = false
    this._engine = engine
    this._piece = this.startPiece
    this._missing = this.length
    this._reading = false
    this._notifying = false
    this._critical = Math.min(1024 * 1024 / pieceLength, 2) | 0
    this._offset = offset - this.startPiece * pieceLength
  }
  
  FileStream.prototype.num2s = function (num) {
    if (num / (1024 * 1024 * 1024) | 0 > 0 ) {
      var ret = num / (1024 * 1024 * 1024) | 0
      return  ret + 'G'
    } else if (num / (1024 * 1024) | 0 > 0 ) {
      var ret = num / (1024 * 1024) | 0
      return  ret + 'M'
    } else if (num / (1024) | 0 > 0 ) {
      var ret = num / (1024) | 0
      return  ret + 'Kb'
    } else {
      return num + 'b'
    }
  }
  
  util.inherits(FileStream, stream.Readable)
  
  FileStream.prototype._read = function () {
    if (this._reading) return
    this._reading = true
    this.notify()
  }
  
  FileStream.prototype.notify = function () {
    if (!this._reading || !this._missing) return
    if (!this._engine.bitfield.get(this._piece)) return this._engine.critical(this._piece, this._critical)
  
    var self = this
  
    if (this._notifying) return
    this._notifying = true
    this._engine.store.get(this._piece++, function (err, buffer) {
      self._notifying = false
  
      if (self._destroyed || !self._reading) return
  
      if (err) return self.destroy(err)
  
      if (self._offset) {
        buffer = buffer.slice(self._offset)
        self._offset = 0
      }
  
      if (self._missing < buffer.length) buffer = buffer.slice(0, self._missing)
  
      self._missing -= buffer.length
  
      if (!self._missing) {
        self.push(buffer)
        self.push(null)
        return
      }
  
      self._reading = false
      self.push(buffer)
    })
  }
  
  FileStream.prototype.destroy = function () {
    if (this._destroyed) return
    this._destroyed = true
    this.emit('close')
  }
  
  module.exports = FileStream
  