/* DBOperationHelper takes an array of HelperSpecs.
   arg0: Length of Array
   arg1: Array of HelperSpecs
   arg2: DBTransactionContext *
   arg3: Old DBOperationSet wrapper (for recycling)

   Returns: DBOperationSet
*/
Handle<Value> DBOperationHelper(const Arguments &args) {
  HandleScope scope;

  int length = args[0]->Int32Value();
  const Local<Object> array = args[1]->ToObject();
  DBTransactionContext *txc = unwrapPointer<DBTransactionContext *>(args[2]->ToObject());
  Handle<Value> oldWrapper = args[3];

  DBOperationSet * pendingOps = new DBOperationSet(txc, length);

  for(int i = 0 ; i < length ; i++) {
    Handle<Object> spec = array->Get(i)->ToObject();

    int opcode  = spec->Get(HELPER_OPCODE)->Int32Value();
    bool is_vo  = spec->Get(HELPER_IS_VO)->ToBoolean()->Value();
    bool op_ok  = spec->Get(HELPER_IS_VALID)->ToBoolean()->Value();

    KeyOperation * op = pendingOps->getKeyOperation(i);
    
    if(op_ok) {
      op->opcode = opcode;
      if(is_vo) DBOperationHelper_VO(spec, *op);
      else      DBOperationHelper_NonVO(spec, *op);
    }
  }
  
  if(oldWrapper->IsObject()) {
    return DBOperationSet_Recycle(oldWrapper->ToObject(), pendingOps);
  } else {
    return DBOperationSet_Wrapper(pendingOps);
  }
}
/* DBOperationHelper takes an array of HelperSpecs.
   arg0: Length of Array
   arg1: Array of HelperSpecs
   arg2: TransactionImpl *
   arg3: Old BatchImpl wrapper (for recycling)

   Returns: BatchImpl
*/
void DBOperationHelper(const Arguments &args) {
  EscapableHandleScope scope(args.GetIsolate());

  int length = args[0]->Int32Value();
  const Local<Object> array = args[1]->ToObject();
  TransactionImpl *txc = unwrapPointer<TransactionImpl *>(args[2]->ToObject());
  Handle<Value> oldWrapper = args[3];

  BatchImpl * pendingOps = new BatchImpl(txc, length);

  for(int i = 0 ; i < length ; i++) {
    Handle<Object> spec = array->Get(i)->ToObject();

    int opcode  = spec->Get(HELPER_OPCODE)->Int32Value();
    bool is_vo  = spec->Get(HELPER_IS_VO)->ToBoolean()->Value();
    bool op_ok  = spec->Get(HELPER_IS_VALID)->ToBoolean()->Value();

    KeyOperation * op = pendingOps->getKeyOperation(i);
    
    if(op_ok) {
      op->opcode = opcode;
      if(is_vo) DBOperationHelper_VO(spec, *op);
      else      DBOperationHelper_NonVO(spec, *op);
    }
  }
  
  if(oldWrapper->IsObject()) {
    args.GetReturnValue().Set(BatchImpl_Recycle(oldWrapper->ToObject(), pendingOps));
  } else {
    args.GetReturnValue().Set(BatchImpl_Wrapper(pendingOps));
  }
}
Handle<Value> DBOperationHelper(const Arguments &args) {
  return
    args[3]->ToBoolean()->Value() ?
      DBOperationHelper_VO(args) : DBOperationHelper_NonVO(args);
}