SRC_DIR = '../../src/log/'

fs = require 'fs'
utils = require '../TestUtils.coffee'
Addr64 = (require SRC_DIR + 'Addr64.coffee').Addr64
LogUtil = (require SRC_DIR + 'LogUtil.coffee').LogUtil
LoggableToWrite = (require SRC_DIR + 'LoggableToWrite.coffee').LoggableToWrite
NullLoggable = (require SRC_DIR + 'NullLoggable.coffee').NullLoggable
RandomAccessLoggable =
  (require SRC_DIR + 'RandomAccessLoggable.coffee').RandomAccessLoggable
Reader = (require SRC_DIR + '../io/Reader.coffee').Reader
Writer = (require SRC_DIR + '../io/Writer.coffee').Writer
ArrayByteIterable =
  (require SRC_DIR + '../database/impl/iterate/ArrayByteIterable.coffee').
  ArrayByteIterable

addrs = new Object()
reader = new Object()

exports.setUp = (callback) ->
  path = utils.getNewDirName()
  try
    fs.mkdirSync path, '0777'
  catch e
  writer = Writer.create$String$int path, 1
  reader = Reader.create$String$int$int$int path, 1, 256, 10
  wl = LoggableToWrite.create$int$ByteIterable$int 1,
          (ArrayByteIterable.create$Buffer new Buffer "Value 1st."), 1
  addrs[1] = writer.write$Loggable wl
  wl = LoggableToWrite.create$int$ByteIterable$int 1,
          (ArrayByteIterable.create$Buffer new Buffer "Value 2nd....."), 2
  addrs[2] = writer.write$Loggable wl
  wl = LoggableToWrite.create$int$ByteIterable$int 1,
          (ArrayByteIterable.create$Buffer new Buffer "Value 3rd."), 3
  addrs[3] = writer.write$Loggable wl
  wl = LoggableToWrite.create$int$ByteIterable 1,
          (ArrayByteIterable.create$Buffer new Buffer "Value 4th.")
  addrs[4] = writer.write$Loggable wl
  writer.padWithNulls()
  addrs[5] = Addr64.create$int$int 0, 1000
  writer.once 'close', () =>
    callback()
  writer.close$emit()

#    0123456789abcdef
#    ||||||||||||||||
# 00-11lValue 1st.12l
# 16-Value 2nd.....13
# 32-lValue 3rd.14lVa
# 48-lue 4th.00000000

exports.testFirstRecord = (test) ->
  test.expect 10
  addrStr = Addr64.addr64ToString$Addr64$int(addrs[1], LogUtil.LOG_NAME_BASE)
  reader.on 'read' + addrStr, (rl) =>
    test.equal rl.address.toFloat(), 0
    test.equal rl.type, 1
    test.equal rl.structureId, 1
    test.equal rl.headerLength, 3
    test.equal rl.length_, 13
    data = rl.getData()
    test.equal data.address.toFloat(), 3
    res = data.compare$int$int$ByteIterable$emit(0, 10,
            ArrayByteIterable.create$Buffer(new Buffer("Value 1st.")))
    test.equal res, 0
    it = data.iterator()
    test.equal it.next$emit(), 0x56
    test.equal it.next$emit(), 0x61
    test.equal it.next$emit(), 0x6c
    test.done()
  reader.read$Addr64$emit addrs[1]

exports.testSecondRecord = (test) ->
  test.expect 7
  addrStr = Addr64.addr64ToString$Addr64$int(addrs[2], LogUtil.LOG_NAME_BASE)
  reader.on 'read' + addrStr, (rl) =>
    test.equal rl.address.toFloat(), 13
    test.equal rl.type, 1
    test.equal rl.structureId, 2
    test.equal rl.headerLength, 3
    test.equal rl.length_, 17
    data = rl.getData()
    test.equal data.address.toFloat(), 16
    res = data.compare$int$int$ByteIterable$emit(0, 14,
            ArrayByteIterable.create$Buffer(new Buffer("Value 2nd.....")))
    test.equal res, 0
    test.done()
  reader.read$Addr64$emit addrs[2]

exports.testThirdRecord = (test) ->
  test.expect 7
  addrStr = Addr64.addr64ToString$Addr64$int(addrs[3], LogUtil.LOG_NAME_BASE)
  reader.on 'read' + addrStr, (rl) =>
    test.equal rl.address.toFloat(), 30
    test.equal rl.type, 1
    test.equal rl.structureId, 3
    test.equal rl.headerLength, 3
    test.equal rl.length_, 13
    data = rl.getData()
    test.equal data.address.toFloat(), 33
    res = data.compare$int$int$ByteIterable$emit(0, 10,
            ArrayByteIterable.create$Buffer(new Buffer("Value 3rd...")))
    test.equal res, -2
    test.done()
  reader.read$Addr64$emit addrs[3]

exports.testForthRecord = (test) ->
  test.expect 7
  addrStr = Addr64.addr64ToString$Addr64$int(addrs[4], LogUtil.LOG_NAME_BASE)
  reader.on 'read' + addrStr, (rl) =>
    test.equal rl.address.toFloat(), 43
    test.equal rl.type, 1
    test.equal rl.structureId, LoggableToWrite.NO_STRUCTURE_ID
    test.equal rl.headerLength, 3
    test.equal rl.length_, 13
    data = rl.getData()
    test.equal data.address.toFloat(), 46
    res = data.compare$int$int$ByteIterable$emit(0, 10,
            ArrayByteIterable.create$Buffer(new Buffer("Value 4th")))
    test.equal res, 1
    test.done()
  reader.read$Addr64$emit addrs[4]

exports.testLastRecord = (test) ->
  test.expect 5
  addrStr = Addr64.addr64ToString$Addr64$int(addrs[5], LogUtil.LOG_NAME_BASE)
  reader.on 'read' + addrStr, (rl) =>
    test.equal rl.address.toFloat(), 1000
    test.equal rl.type, 0
    test.equal rl.structureId, 0
    test.equal rl.headerLength, 1
    test.equal rl.length_, 1
    test.done()
  reader.read$Addr64$emit addrs[5]
