EventEmitter = (require 'events').EventEmitter
Addr64 = (require './Addr64.coffee').Addr64
LogUtil = (require './LogUtil.coffee').LogUtil
UnsupportedOperationError =
  (require '../errors/UnsupportedOperationError.coffee').
  UnsupportedOperationError

# Stops at the end of log or on the file hole.
class RandomAccessLoggableIterator extends EventEmitter
  # @private
  log: undefined
  # @private
  address: undefined

  # Constructor.
  #
  # @param log
  # @param startAddress
  @create$Log$Addr64: (log, startAddress, o) ->
    if !o? then o = new RandomAccessLoggableIterator
    o.log = log
    o.address = startAddress
    return o

  getHighAddress: () ->
    return @address

  # Get next element.
  #
  # @return next loggable or undefined. If undefined 'next' event is emitted.
  next$emit: () ->
    finish = (result) =>
      @emit 'next', result
    onNext = (result) =>
      @address = @address.plus$int result.length()
      finish result
    addrString = Addr64.
    addr64ToString$Addr64$int(@address, LogUtil.LOG_NAME_BASE)
    @log.once 'read' + addrString, (result) =>
      onNext result
    result = @log.read$Addr64$emit @address
    if result?
      @log.removeAllListeners 'read' + addrString
      onNext result
    else
      return undefined

  hasNext: () ->
    return @log.hasAddress$Addr64 @address

  remove: () ->
    throw new UnsupportedOperationError()

exports.RandomAccessLoggableIterator = RandomAccessLoggableIterator