(function() {
  var Range, SelectNext, _;

  _ = require('underscore-plus');

  Range = require('atom').Range;

  module.exports = SelectNext = (function() {
    SelectNext.prototype.selectionRanges = null;

    function SelectNext(editor) {
      this.editor = editor;
      this.selectionRanges = [];
    }

    SelectNext.prototype.findAndSelectNext = function() {
      if (this.editor.getLastSelection().isEmpty()) {
        return this.selectWord();
      } else {
        return this.selectNextOccurrence();
      }
    };

    SelectNext.prototype.findAndSelectAll = function() {
      if (this.editor.getLastSelection().isEmpty()) {
        this.selectWord();
      }
      return this.selectAllOccurrences();
    };

    SelectNext.prototype.undoLastSelection = function() {
      this.updateSavedSelections();
      if (this.selectionRanges.length < 1) {
        return;
      }
      if (this.selectionRanges.length > 1) {
        this.selectionRanges.pop();
        this.editor.setSelectedBufferRanges(this.selectionRanges);
      } else {
        this.editor.clearSelections();
      }
      return this.editor.scrollToCursorPosition();
    };

    SelectNext.prototype.skipCurrentSelection = function() {
      var lastSelection;
      this.updateSavedSelections();
      if (this.selectionRanges.length < 1) {
        return;
      }
      if (this.selectionRanges.length > 1) {
        lastSelection = this.selectionRanges.pop();
        this.editor.setSelectedBufferRanges(this.selectionRanges);
        return this.selectNextOccurrence({
          start: lastSelection.end
        });
      } else {
        this.selectNextOccurrence();
        this.selectionRanges.shift();
        if (this.selectionRanges.length < 1) {
          return;
        }
        return this.editor.setSelectedBufferRanges(this.selectionRanges);
      }
    };

    SelectNext.prototype.selectWord = function() {
      this.editor.selectWordsContainingCursors();
      return this.wordSelected = this.isWordSelected(this.editor.getLastSelection());
    };

    SelectNext.prototype.selectAllOccurrences = function() {
      var range;
      range = [[0, 0], this.editor.getEofBufferPosition()];
      return this.scanForNextOccurrence(range, (function(_this) {
        return function(_arg) {
          var range, stop;
          range = _arg.range, stop = _arg.stop;
          return _this.addSelection(range);
        };
      })(this));
    };

    SelectNext.prototype.selectNextOccurrence = function(options) {
      var range, startingRange, _ref;
      if (options == null) {
        options = {};
      }
      startingRange = (_ref = options.start) != null ? _ref : this.editor.getSelectedBufferRange().end;
      range = this.findNextOccurrence([startingRange, this.editor.getEofBufferPosition()]);
      if (range == null) {
        range = this.findNextOccurrence([[0, 0], this.editor.getSelections()[0].getBufferRange().start]);
      }
      if (range != null) {
        return this.addSelection(range);
      }
    };

    SelectNext.prototype.findNextOccurrence = function(scanRange) {
      var foundRange;
      foundRange = null;
      this.scanForNextOccurrence(scanRange, function(_arg) {
        var range, stop;
        range = _arg.range, stop = _arg.stop;
        foundRange = range;
        return stop();
      });
      return foundRange;
    };

    SelectNext.prototype.addSelection = function(range) {
      var disposable, selection;
      selection = this.editor.addSelectionForBufferRange(range);
      this.updateSavedSelections(selection);
      return disposable = selection.onDidDestroy((function(_this) {
        return function() {
          _this.wordSelected = null;
          return disposable.dispose();
        };
      })(this));
    };

    SelectNext.prototype.scanForNextOccurrence = function(range, callback) {
      var nonWordCharacters, selection, text;
      selection = this.editor.getLastSelection();
      text = _.escapeRegExp(selection.getText());
      if (this.wordSelected == null) {
        this.wordSelected = this.isWordSelected(selection);
      }
      if (this.wordSelected) {
        nonWordCharacters = atom.config.get('editor.nonWordCharacters');
        text = "(^|[ \t" + (_.escapeRegExp(nonWordCharacters)) + "]+)" + text + "(?=$|[\\s" + (_.escapeRegExp(nonWordCharacters)) + "]+)";
      }
      return this.editor.scanInBufferRange(new RegExp(text, 'g'), range, function(result) {
        var prefix;
        if (prefix = result.match[1]) {
          result.range = result.range.translate([0, prefix.length], [0, 0]);
        }
        return callback(result);
      });
    };

    SelectNext.prototype.updateSavedSelections = function(selection) {
      var s, selectionRange, selections, _i, _len, _results;
      if (selection == null) {
        selection = null;
      }
      selections = this.editor.getSelections();
      if (selections.length < 3) {
        this.selectionRanges = [];
      }
      if (this.selectionRanges.length === 0) {
        _results = [];
        for (_i = 0, _len = selections.length; _i < _len; _i++) {
          s = selections[_i];
          _results.push(this.selectionRanges.push(s.getBufferRange()));
        }
        return _results;
      } else if (selection) {
        selectionRange = selection.getBufferRange();
        if (this.selectionRanges.indexOf(selectionRange) !== -1) {
          return;
        }
        return this.selectionRanges.push(selectionRange);
      }
    };

    SelectNext.prototype.isNonWordCharacter = function(character) {
      var nonWordCharacters;
      nonWordCharacters = atom.config.get('editor.nonWordCharacters');
      return new RegExp("[ \t" + (_.escapeRegExp(nonWordCharacters)) + "]").test(character);
    };

    SelectNext.prototype.isNonWordCharacterToTheLeft = function(selection) {
      var range, selectionStart;
      selectionStart = selection.getBufferRange().start;
      range = Range.fromPointWithDelta(selectionStart, 0, -1);
      return this.isNonWordCharacter(this.editor.getTextInBufferRange(range));
    };

    SelectNext.prototype.isNonWordCharacterToTheRight = function(selection) {
      var range, selectionEnd;
      selectionEnd = selection.getBufferRange().end;
      range = Range.fromPointWithDelta(selectionEnd, 0, 1);
      return this.isNonWordCharacter(this.editor.getTextInBufferRange(range));
    };

    SelectNext.prototype.isWordSelected = function(selection) {
      var containsOnlyWordCharacters, lineRange, nonWordCharacterToTheLeft, nonWordCharacterToTheRight, selectionRange;
      if (selection.getBufferRange().isSingleLine()) {
        selectionRange = selection.getBufferRange();
        lineRange = this.editor.bufferRangeForBufferRow(selectionRange.start.row);
        nonWordCharacterToTheLeft = _.isEqual(selectionRange.start, lineRange.start) || this.isNonWordCharacterToTheLeft(selection);
        nonWordCharacterToTheRight = _.isEqual(selectionRange.end, lineRange.end) || this.isNonWordCharacterToTheRight(selection);
        containsOnlyWordCharacters = !this.isNonWordCharacter(selection.getText());
        return nonWordCharacterToTheLeft && nonWordCharacterToTheRight && containsOnlyWordCharacters;
      } else {
        return false;
      }
    };

    return SelectNext;

  })();

}).call(this);
