 _ = require 'underscore-plus'
 {CompositeDisposable} = require 'atom'
 {inspect} = require 'util'
+
+# Moving strategy
+# -------------------------
+# Two wise. correspoinding submode of visual-mode is below
+#  - Linewise: linewise, characterwise(in case some selection is multi-row)
+#  - Characterwise: characterwise(in case all selection is single-row), blockwise
+#
+# Four direction
+#   ['up', 'down', 'right', 'left']
+#
+# Movability
+#  up
+#    - Linewise: can't move upward if row is 0
+#    - Characterwise: can't move upward if top selection is at row 0
+#  down
+#    - Linewise: always movable since last row is automatically extended.
+#    - Characterwise: always movable since last row is automatically extended.
+#  right
+#    - Linewise: always movable since EOL is automatically extended.
+#    - Characterwise: always movable since EOL is automatically extended.
+#  left
+#    - Linewise: always true since indent/outdent command can handle it.
+#    - Characterwise: can't move if start of selection is at column 0
+#
+# Moving method
+#  up
+#    - Linewise: rotate linewise
+#    - Characterwise: swap single-row selection with upper block
+#  down
+#    - Linewise: rotate linewise
+#    - Characterwise: swap single-row selection with lower block
+#  right
+#    - Linewise: indent line
+#    - Characterwise: rotate charater in single-row selection.
+#  left
+#    - Linewise: outdent line
+#    - Characterwise: rotate charater in single-row selection.
+
 
 requireFrom = (pack, path) ->
   packPath = atom.packages.resolvePackagePath(pack)

  isOverwrite: ->
    atom.config.get('vim-mode-plus-move-selected-text.overwrite')

  execute: ->
    @withUndoJoin =>
      selections = @editor.getSelectionsOrderedByBufferPosition()
      topSelection = selections[0]
      selections.reverse() if @direction is 'down'
      @editor.transact =>
        @countTimes =>
          return if (not @isLinewise()) and (not @isMovable(topSelection))
          for selection in selections
            @mutate(selection) if @isMovable(selection)

  getOverwrittenBySelection: ->
    overwrittenBySelection = new Map
    isLinewise = @isLinewise()
    @editor.getSelections().forEach (selection) ->

    range = selection.getBufferRange().translate(translation...)
    selection.setBufferRange(range)

    # up and down is only for linewise
    # left and right is only for characterwise
    text = switch @direction
      when 'up', 'down' then swrap(selection).lineTextForBufferRows()
      when 'right', 'left' then selection.getText().split('')

    rotated = @rotateText(text, selection, @isOverwrite())
    newText = if @isLinewise()
      rotated.join("\n") + "\n"
    else
      rotated.join('')

    range = selection.insertText(newText)
    range = range.translate(translation.reverse()...)
