###*
# Expose an elasticsearch query that returns hits or docs as a stream of hits or docs.
#
# Expect the query to be a JSON object where the from property defines the offset
# and the limit defines the page size.
# Expect the client to return a parsed JSON.
###

###*
# @param queryExec an executable query functions that takes 2 arguments: the offset and a callback.
###

ReadableHits = (queryExec, parseHit) ->
  if !(this instanceof ReadableHits)
    return new ReadableHits(queryExec)
  Readable.call this, objectMode: true
  @queryExec = queryExec
  @total = -1
  @from = 0
  @_next = true
  # current iteration through the page
  @_hits = []
  @_current = 0
  @parseHit = parseHit or identity
  return

identity = (hit) ->
  hit

'use strict'
Readable = require('stream').Readable
module.exports = ReadableHits
ReadableHits.prototype = Object.create(Readable.prototype, constructor: value: ReadableHits)

ReadableHits::_read = ->
  #size) {
  @_current++
  if @_current >= @_hits.length
    if !@_next
      return @push(null)
    @_fetchNextPage()
  else
    @_shift()
  return

ReadableHits::_fetchNextPage = ->
  #size) {
  self = this
  @queryExec @from, (e, resp) ->
    self._current = 0
    if e
      self.hits = []
      self._next = false
      self.emit 'error', e
      return self.push(null)
    self.total = resp.hits.total
    self._hits = resp.hits.hits
    self.from += self._hits.length
    if self.from >= self.total
      self._next = false
      # we got them all.
    if !self._hits.length
      # nothing here: end the stream.
      # self._next = false; // precaution but we should not really need this line.
      return self.push(null)
    self._shift()
    return
  return

ReadableHits::_shift = ->
  @push @parseHit(@_hits[@_current])
  return

ReadableHits::destroy = ->
  if @destroyed
    return
  @destroyed = true
  @_next = false
  @unpipe()
  return

# ---
# generated by js2coffee 2.2.0
