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

fs = require 'fs'
utils = require '../TestUtils.coffee'
Environment = (require SRC_DIR + 'list_env/Environment.coffee').Environment
EnvironmentConfig =
  (require SRC_DIR + 'list_env/EnvironmentConfig.coffee').EnvironmentConfig
Store = (require SRC_DIR + 'list_env/Store.coffee').Store
StoreConfiguration =
  (require SRC_DIR + 'database/persistence/StoreConfiguration.coffee').
  StoreConfiguration
ArrayByteIterable =
  (require SRC_DIR + 'database/impl/iterate/ArrayByteIterable.coffee').
  ArrayByteIterable
EventEmitter = (require 'events').EventEmitter
Cursor = (require SRC_DIR + 'list_env/Cursor.coffee').Cursor

path = undefined
env = undefined
envConfig = undefined
store = undefined
storeConfig = undefined
txn = undefined
temp = undefined
cursor = undefined

exports.setUp = (callback) =>
  path = utils.getNewDirName()
  fs.mkdirSync path, '0777'
  temp = new EventEmitter()
  envConfig = EnvironmentConfig.create()
  env = Environment.create$String$EnvironmentConfig path, envConfig
  txn = env.beginTransaction()
  callback()

exports.testCreation = (test) =>
  test.expect 4
  env.once 'openStore', (store) =>
    cursor = store.openCursor$TransactionDescriptor txn
    test.ok cursor?
    test.ok cursor.node?
    test.ok !cursor.getKey()?
    test.ok !cursor.getValue()?
    test.done()
  env.openStore$String$StoreConfiguration$emit 'FirstStore',
          StoreConfiguration.DBCONFIG_WITHOUT_DUPLICATES

writeToStore$Store = (store, i, j) =>
  n = i
  store.on 'put', () =>
    n += 1
    if n == j
      temp.emit 'write'
    else
      store.put$TransactionDescriptor$ByteIterable$ByteIterable$emit txn,
              ArrayByteIterable.create$Buffer(new Buffer("Key" + n.toString())),
              ArrayByteIterable.create$Buffer(new Buffer("Value" + n.toString()))
  store.put$TransactionDescriptor$ByteIterable$ByteIterable$emit txn,
          ArrayByteIterable.create$Buffer(new Buffer("Key" + n.toString())),
          ArrayByteIterable.create$Buffer(new Buffer("Value" + n.toString()))

exports.testGetNext = (test) =>
  test.expect 32
  env.once 'openStore', (store) =>
    temp.once 'write', () =>
      txn.once 'commit', () =>
        txn = env.beginTransaction()
        env.once 'openStore', (store) =>
          cursor = store.openCursor$TransactionDescriptor txn
          test.equal cursor.count(), 10
          n = 0
          cursor.on 'getNext', (success) =>
            n += 1
            if n <= 10
              test.ok success
              test.ok cursor.getValue()?
              test.ok cursor.getKey()?
              cursor.getNext$emit()
            else
              test.ok !success
              test.done()
          cursor.getNext$emit()
        env.openStore$String$StoreConfiguration$emit 'FirstStore',
                StoreConfiguration.DBCONFIG_WITHOUT_DUPLICATES
      txn.commit$emit()
    writeToStore$Store store, 0, 10
  env.openStore$String$StoreConfiguration$emit 'FirstStore',
          StoreConfiguration.DBCONFIG_WITHOUT_DUPLICATES

exports.testLastAndPrev = (test) ->
  test.expect 30
  env.once 'openStore', (store) =>
    temp.once 'write', () =>
      txn.once 'commit', () =>
        txn = env.beginTransaction()
        env.once 'openStore', (store) =>
          cursor = store.openCursor$TransactionDescriptor txn
          cursor.once 'getLast', () =>
            test.ok cursor.getValue()?
            test.ok cursor.getKey()?
            for i in [1..9]
              res = cursor.getPrev()
              test.ok res
              test.ok cursor.getValue()?
              test.ok cursor.getKey()?
            res = cursor.getPrev()
            test.ok !res
            test.done()
          cursor.getLast$emit()
        env.openStore$String$StoreConfiguration$emit 'FirstStore',
                StoreConfiguration.DBCONFIG_WITHOUT_DUPLICATES
      txn.commit$emit()
    writeToStore$Store store, 0, 10
  env.openStore$String$StoreConfiguration$emit 'FirstStore',
          StoreConfiguration.DBCONFIG_WITHOUT_DUPLICATES
