   getFirstIndex: () ->
     @_firstIdx
 
-  add: (idx, rowPromise) ->
+  add: (idx, rowFn) ->
     d = Q.defer()
 
     if not @_firstIdx?

    else if @_lastIdx < idx
      @_lastIdx = idx

    rowPromise
    .then (row) =>
      @_incommingRow idx, row, d
    .fail (error) ->
      d.reject error
    .done()

    d.promise

  _incommingRow: (idx, row, defer) ->
    @_buffer["#{idx}"] = {idx: idx, row: row, defer: defer}

    @_checkWhetherFinished()

  _checkWhetherFinished: () ->
    if not @_written and @_finished and @_allRowsFinished()
      _.each @_getIdxs(), (idx) =>
        box = @_buffer["#{idx}"]
        box.defer.resolve box.row
      @_written = true

  _allRowsFinished: () ->
    _.every @_getIdxs(), (idx) =>

        groupValue = if @_mapping.groupColumn? then inObj[@_mapping.groupColumn] else "#{idx}"
        buffer = buffers[groupValue]

        lastControlPromise =
          if not buffer?
            buffer = new GroupBuffer()
            buffers[groupValue] = buffer

            if lastBufferGroupValue?
              buffers[lastBufferGroupValue].finished()
            else
              Q(false)
          else
            Q(false)

        [rowPromise, controlPromise] = buffer.add idx, =>
          bufferFirstIdx = buffer.getFirstIndex() or idx

          @_mapping.transformRow requiredGroups, inObj,
            index: if @_includesHeaderRow then idx - 1 else idx
            groupFirstIndex: if @_includesHeaderRow then bufferFirstIdx - 1 else bufferFirstIdx
            groupContext: buffer.getContext()

        rowPromise
        .then (convertedPerGroup) =>
          _.each writers, (w) =>
            result = @_convertFromObject(w.newHeaders, _.find(convertedPerGroup, (c) -> c.group is w.group).row)
