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

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

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

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()))

getAllRecords$Store = (store, test) =>
  n = 0
  store.on 'get', (value) =>
    if value?
      test.equal 0, value.compareTo$ByteIterable$emit ArrayByteIterable.
      create$Buffer(new Buffer("Value" + n.toString()))
    else
      test.ok false, 'Value is not defined'
    n += 1
    if n == 10
      temp.emit 'getAll'
    else
      store.get$TransactionDescriptor$ByteIterable$emit txn,
              ArrayByteIterable.create$Buffer(new Buffer("Key" + n.toString()))
  store.get$TransactionDescriptor$ByteIterable$emit txn,
          ArrayByteIterable.create$Buffer(new Buffer("Key" + n.toString()))

exports.testCreation = (test) =>
  test.expect 2
  env.once 'openStore', (store) =>
    test.equal store.getName(), 'FirstStore'
    test.equal store.list.log.directory, path + 'FirstStore/'
    test.done()
  env.openStore$String$StoreConfiguration$emit 'FirstStore',
          StoreConfiguration.DBCONFIG_WITHOUT_DUPLICATES

exports.testTransactionCommit = (test) =>
  test.expect 10
  env.once 'openStore', (store) =>
    done = () =>
      test.done()

    temp.on 'getAll', () =>
      done()

    txn.on 'commit', () =>
      env.once 'openStore', (store) =>
        getAllRecords$Store store, test
      txn = env.beginTransaction()
      env.openStore$String$StoreConfiguration$emit 'FirstStore',
              StoreConfiguration.DBCONFIG_WITHOUT_DUPLICATES

    temp.on 'write', () =>
      txn.commit$emit()

    writeToStore$Store store, 0, 10
  env.openStore$String$StoreConfiguration$emit 'FirstStore',
          StoreConfiguration.DBCONFIG_WITHOUT_DUPLICATES

exports.testTransactionAbort = (test) =>
  test.expect 11
  env.once 'openStore', (store) =>
    done = () =>
      test.done()

    temp.once 'getAll', () =>
      test.equal env.getDiskUsage(), 300
      done()

    txn.once 'abort', () =>
      env.once 'openStore', (store) =>
        getAllRecords$Store store, test
      txn = env.beginTransaction()
      env.openStore$String$StoreConfiguration$emit 'FirstStore',
              StoreConfiguration.DBCONFIG_WITHOUT_DUPLICATES

    txn.once 'commit', () =>
      txn.abort$emit()

    temp.once 'write', () =>
      txn.commit$emit()

    writeToStore$Store store, 0, 10
  env.openStore$String$StoreConfiguration$emit 'FirstStore',
          StoreConfiguration.DBCONFIG_WITHOUT_DUPLICATES
