(function() {
  var ReactBookmarks, Subscriber, _,
    __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

  _ = require('underscore-plus');

  Subscriber = require('emissary').Subscriber;

  module.exports = ReactBookmarks = (function() {
    Subscriber.includeInto(ReactBookmarks);

    function ReactBookmarks(editor) {
      this.editor = editor;
      this.jumpToBookmark = __bind(this.jumpToBookmark, this);
      this.jumpToPreviousBookmark = __bind(this.jumpToPreviousBookmark, this);
      this.jumpToNextBookmark = __bind(this.jumpToNextBookmark, this);
      this.clearBookmarks = __bind(this.clearBookmarks, this);
      this.addDecorationsForBookmarks = __bind(this.addDecorationsForBookmarks, this);
      this.toggleBookmark = __bind(this.toggleBookmark, this);
      this.subscribe(atom.commands.add(atom.views.getView(this.editor), {
        'bookmarks:toggle-bookmark': this.toggleBookmark,
        'bookmarks:jump-to-next-bookmark': this.jumpToNextBookmark,
        'bookmarks:jump-to-previous-bookmark': this.jumpToPreviousBookmark,
        'bookmarks:clear-bookmarks': this.clearBookmarks
      }));
      this.addDecorationsForBookmarks();
    }

    ReactBookmarks.prototype.destroy = function() {
      return this.commandsDisposable.destroy();
    };

    ReactBookmarks.prototype.toggleBookmark = function() {
      var bookmark, bookmarks, cursor, cursors, position, _i, _len, _results;
      cursors = this.editor.getCursors();
      _results = [];
      for (_i = 0, _len = cursors.length; _i < _len; _i++) {
        cursor = cursors[_i];
        position = cursor.getBufferPosition();
        bookmarks = this.findBookmarkMarkers({
          startBufferRow: position.row
        });
        if ((bookmarks != null ? bookmarks.length : void 0) > 0) {
          _results.push((function() {
            var _j, _len1, _results1;
            _results1 = [];
            for (_j = 0, _len1 = bookmarks.length; _j < _len1; _j++) {
              bookmark = bookmarks[_j];
              _results1.push(bookmark.destroy());
            }
            return _results1;
          })());
        } else {
          _results.push(this.createBookmarkMarker(position.row));
        }
      }
      return _results;
    };

    ReactBookmarks.prototype.addDecorationsForBookmarks = function() {
      var bookmark, _i, _len, _ref;
      _ref = this.findBookmarkMarkers();
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        bookmark = _ref[_i];
        if (bookmark.isValid()) {
          this.editor.decorateMarker(bookmark, {
            type: 'line-number',
            "class": 'bookmarked'
          });
        }
      }
      return null;
    };

    ReactBookmarks.prototype.clearBookmarks = function() {
      var bookmark, _i, _len, _ref, _results;
      _ref = this.findBookmarkMarkers();
      _results = [];
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        bookmark = _ref[_i];
        _results.push(bookmark.destroy());
      }
      return _results;
    };

    ReactBookmarks.prototype.jumpToNextBookmark = function() {
      return this.jumpToBookmark('getNextBookmark');
    };

    ReactBookmarks.prototype.jumpToPreviousBookmark = function() {
      return this.jumpToBookmark('getPreviousBookmark');
    };

    ReactBookmarks.prototype.jumpToBookmark = function(getBookmarkFunction) {
      var bookmarkMarker, cursor, position;
      cursor = this.editor.getLastCursor();
      position = cursor.getBufferPosition();
      bookmarkMarker = this[getBookmarkFunction](position.row);
      if (bookmarkMarker) {
        return this.editor.setSelectedBufferRange(bookmarkMarker.getBufferRange(), {
          autoscroll: true
        });
      } else {
        return atom.beep();
      }
    };

    ReactBookmarks.prototype.getPreviousBookmark = function(bufferRow) {
      var bookmarkIndex, markers;
      markers = this.findBookmarkMarkers();
      if (!markers.length) {
        return null;
      }
      if (markers.length === 1) {
        return markers[0];
      }
      bookmarkIndex = _.sortedIndex(markers, bufferRow, function(marker) {
        if (marker.getBufferRange) {
          return marker.getBufferRange().start.row;
        } else {
          return marker;
        }
      });
      bookmarkIndex--;
      if (bookmarkIndex < 0) {
        bookmarkIndex = markers.length - 1;
      }
      return markers[bookmarkIndex];
    };

    ReactBookmarks.prototype.getNextBookmark = function(bufferRow) {
      var bookmarkIndex, markers;
      markers = this.findBookmarkMarkers();
      if (!markers.length) {
        return null;
      }
      if (markers.length === 1) {
        return markers[0];
      }
      bookmarkIndex = _.sortedIndex(markers, bufferRow, function(marker) {
        if (marker.getBufferRange) {
          return marker.getBufferRange().start.row;
        } else {
          return marker;
        }
      });
      if (markers[bookmarkIndex] && markers[bookmarkIndex].getBufferRange().start.row === bufferRow) {
        bookmarkIndex++;
      }
      if (bookmarkIndex >= markers.length) {
        bookmarkIndex = 0;
      }
      return markers[bookmarkIndex];
    };

    ReactBookmarks.prototype.createBookmarkMarker = function(bufferRow) {
      var bookmark, range;
      range = [[bufferRow, 0], [bufferRow, 0]];
      bookmark = this.displayBuffer().markBufferRange(range, this.bookmarkMarkerAttributes({
        invalidate: 'surround'
      }));
      this.subscribe(bookmark.onDidChange(function(_arg) {
        var isValid;
        isValid = _arg.isValid;
        if (!isValid) {
          return bookmark.destroy();
        }
      }));
      this.editor.decorateMarker(bookmark, {
        type: 'line-number',
        "class": 'bookmarked'
      });
      return bookmark;
    };

    ReactBookmarks.prototype.findBookmarkMarkers = function(attributes) {
      if (attributes == null) {
        attributes = {};
      }
      return this.displayBuffer().findMarkers(this.bookmarkMarkerAttributes(attributes));
    };

    ReactBookmarks.prototype.bookmarkMarkerAttributes = function(attributes) {
      if (attributes == null) {
        attributes = {};
      }
      return _.extend(attributes, {
        "class": 'bookmark'
      });
    };

    ReactBookmarks.prototype.displayBuffer = function() {
      return this.editor.displayBuffer;
    };

    return ReactBookmarks;

  })();

}).call(this);
