   setTextInRangeAndSelect
   insertSpacesToPoint
   extendLastBufferRowToRow
+  countChar
 } = require './utils'
 {inspect} = require 'util'
 

            if wasCharacterwise
              @vimState.activate('visual', 'characterwise')

  duplicateLinewise: (selection, count) ->
    {start, end} = selection.getBufferRange()
    rows = swrap(selection).lineTextForBufferRows()
    lineTexts = switch @direction
      when 'up', 'down' then _.flatten([1..count].map -> rows)
      when 'left', 'right' then rows.map (text) -> text.repeat(count+1)

    height = lineTexts.length
    newText = lineTexts.join("\n") + "\n"

    range = switch @direction
      when 'up'
        if @isOverwrite()
          [start.translate([-height, 0]), start]
        else
          [start, start]
      when 'down'
        if @isOverwrite()
          [end, end.translate([+height, 0])]
        else
          [end, end]
      when 'left', 'right'
        selection.getBufferRange()
    setTextInRangeAndSelect(range, newText, selection)

class DuplicateSelectedTextUp extends DuplicateSelectedText
  direction: 'up'

  duplicateBlockwiseSelection: (blockwiseSelection, count) ->
    {selections} = blockwiseSelection


class DuplicateSelectedTextRight extends DuplicateSelectedText
  direction: 'right'

  duplicateLinewise: (selection, count) ->
    getText = ->
      swrap(selection).lineTextForBufferRows()
        .map (text) -> text.repeat(count+1)
        .join("\n") + "\n"

    text = getText()
    range = selection.getBufferRange()
    setTextInRangeAndSelect(range, text, selection)

  duplicateCharacterwise: (selection, count) ->
    getRangeToInsert = (text) =>
      {start, end} = selection.getBufferRange()
      if @isOverwrite()
        width = text.length
        switch @direction
          when 'right' then [end, end.translate([0, +width])]
          when 'left' then [start, start.translate([0, +width])]
      else
        switch @direction
          when 'right' then [end, end]
          when 'left' then [start, start]

    text = selection.getText().repeat(count)
    range = getRangeToInsert(text)
    setTextInRangeAndSelect(range, text, selection)

class DuplicateSelectedTextLeft extends DuplicateSelectedTextRight
  direction: 'left'
