(function() {
  var CompositeDisposable, DisplayMarker, Emitter, ref;

  ref = require('event-kit'), Emitter = ref.Emitter, CompositeDisposable = ref.CompositeDisposable;

  module.exports = DisplayMarker = (function() {

    /*
    Section: Construction and Destruction
     */
    function DisplayMarker(layer, bufferMarker) {
      this.layer = layer;
      this.bufferMarker = bufferMarker;
      this.id = this.bufferMarker.id;
      this.hasChangeObservers = false;
      this.emitter = new Emitter;
      this.disposables = new CompositeDisposable;
      this.destroyed = false;
      this.disposables.add(this.bufferMarker.onDidDestroy(this.destroy.bind(this)));
    }

    DisplayMarker.prototype.destroy = function() {
      if (this.destroyed) {
        return;
      }
      this.destroyed = true;
      this.layer.markersWithDestroyListeners["delete"](this);
      this.bufferMarker.destroy();
      this.emitter.emit('did-destroy');
      this.layer.didDestroyMarker(this);
      this.emitter.dispose();
      return this.disposables.dispose();
    };

    DisplayMarker.prototype.copy = function(params) {
      return this.layer.getMarker(this.bufferMarker.copy(params).id);
    };


    /*
    Section: Event Subscription
     */

    DisplayMarker.prototype.onDidChange = function(callback) {
      if (!this.hasChangeObservers) {
        this.oldHeadBufferPosition = this.getHeadBufferPosition();
        this.oldHeadScreenPosition = this.getHeadScreenPosition();
        this.oldTailBufferPosition = this.getTailBufferPosition();
        this.oldTailScreenPosition = this.getTailScreenPosition();
        this.wasValid = this.isValid();
        this.disposables.add(this.bufferMarker.onDidChange((function(_this) {
          return function(event) {
            return _this.notifyObservers(event.textChanged);
          };
        })(this)));
        this.hasChangeObservers = true;
      }
      return this.emitter.on('did-change', callback);
    };

    DisplayMarker.prototype.onDidDestroy = function(callback) {
      this.layer.markersWithDestroyListeners.add(this);
      return this.emitter.on('did-destroy', callback);
    };


    /*
    Section: TextEditorMarker Details
     */

    DisplayMarker.prototype.isValid = function() {
      return this.bufferMarker.isValid();
    };

    DisplayMarker.prototype.isDestroyed = function() {
      return this.layer.isDestroyed() || this.destroyed;
    };

    DisplayMarker.prototype.isReversed = function() {
      return this.bufferMarker.isReversed();
    };

    DisplayMarker.prototype.isExclusive = function() {
      return this.bufferMarker.isExclusive();
    };

    DisplayMarker.prototype.getInvalidationStrategy = function() {
      return this.bufferMarker.getInvalidationStrategy();
    };

    DisplayMarker.prototype.getProperties = function() {
      return this.bufferMarker.getProperties();
    };

    DisplayMarker.prototype.setProperties = function(properties) {
      return this.bufferMarker.setProperties(properties);
    };

    DisplayMarker.prototype.matchesProperties = function(attributes) {
      attributes = this.layer.translateToBufferMarkerParams(attributes);
      return this.bufferMarker.matchesParams(attributes);
    };


    /*
    Section: Comparing to other markers
     */

    DisplayMarker.prototype.compare = function(otherMarker) {
      return this.bufferMarker.compare(otherMarker.bufferMarker);
    };

    DisplayMarker.prototype.isEqual = function(other) {
      if (!(other instanceof this.constructor)) {
        return false;
      }
      return this.bufferMarker.isEqual(other.bufferMarker);
    };


    /*
    Section: Managing the marker's range
     */

    DisplayMarker.prototype.getBufferRange = function() {
      return this.bufferMarker.getRange();
    };

    DisplayMarker.prototype.getScreenRange = function() {
      return this.layer.translateBufferRange(this.getBufferRange());
    };

    DisplayMarker.prototype.setBufferRange = function(bufferRange, properties) {
      return this.bufferMarker.setRange(bufferRange, properties);
    };

    DisplayMarker.prototype.setScreenRange = function(screenRange, options) {
      return this.setBufferRange(this.layer.translateScreenRange(screenRange, options), options);
    };

    DisplayMarker.prototype.getHeadBufferPosition = function() {
      return this.bufferMarker.getHeadPosition();
    };

    DisplayMarker.prototype.setHeadBufferPosition = function(bufferPosition) {
      return this.bufferMarker.setHeadPosition(bufferPosition);
    };

    DisplayMarker.prototype.getHeadScreenPosition = function(options) {
      return this.layer.translateBufferPosition(this.bufferMarker.getHeadPosition(), options);
    };

    DisplayMarker.prototype.setHeadScreenPosition = function(screenPosition, options) {
      return this.setHeadBufferPosition(this.layer.translateScreenPosition(screenPosition, options));
    };

    DisplayMarker.prototype.getTailBufferPosition = function() {
      return this.bufferMarker.getTailPosition();
    };

    DisplayMarker.prototype.setTailBufferPosition = function(bufferPosition) {
      return this.bufferMarker.setTailPosition(bufferPosition);
    };

    DisplayMarker.prototype.getTailScreenPosition = function(options) {
      return this.layer.translateBufferPosition(this.bufferMarker.getTailPosition(), options);
    };

    DisplayMarker.prototype.setTailScreenPosition = function(screenPosition, options) {
      return this.bufferMarker.setTailPosition(this.layer.translateScreenPosition(screenPosition, options));
    };

    DisplayMarker.prototype.getStartBufferPosition = function() {
      return this.bufferMarker.getStartPosition();
    };

    DisplayMarker.prototype.getStartScreenPosition = function(options) {
      return this.layer.translateBufferPosition(this.getStartBufferPosition(), options);
    };

    DisplayMarker.prototype.getEndBufferPosition = function() {
      return this.bufferMarker.getEndPosition();
    };

    DisplayMarker.prototype.getEndScreenPosition = function(options) {
      return this.layer.translateBufferPosition(this.getEndBufferPosition(), options);
    };

    DisplayMarker.prototype.hasTail = function() {
      return this.bufferMarker.hasTail();
    };

    DisplayMarker.prototype.plantTail = function() {
      return this.bufferMarker.plantTail();
    };

    DisplayMarker.prototype.clearTail = function() {
      return this.bufferMarker.clearTail();
    };

    DisplayMarker.prototype.toString = function() {
      return "[Marker " + this.id + ", bufferRange: " + (this.getBufferRange()) + ", screenRange: " + (this.getScreenRange()) + "}]";
    };


    /*
    Section: Private
     */

    DisplayMarker.prototype.inspect = function() {
      return this.toString();
    };

    DisplayMarker.prototype.notifyObservers = function(textChanged) {
      var changeEvent, isValid, newHeadBufferPosition, newHeadScreenPosition, newTailBufferPosition, newTailScreenPosition;
      if (textChanged == null) {
        textChanged = false;
      }
      newHeadBufferPosition = this.getHeadBufferPosition();
      newHeadScreenPosition = this.getHeadScreenPosition();
      newTailBufferPosition = this.getTailBufferPosition();
      newTailScreenPosition = this.getTailScreenPosition();
      isValid = this.isValid();
      if (isValid === this.wasValid && newHeadBufferPosition.isEqual(this.oldHeadBufferPosition) && newHeadScreenPosition.isEqual(this.oldHeadScreenPosition) && newTailBufferPosition.isEqual(this.oldTailBufferPosition) && newTailScreenPosition.isEqual(this.oldTailScreenPosition)) {
        return;
      }
      changeEvent = {
        oldHeadScreenPosition: this.oldHeadScreenPosition,
        newHeadScreenPosition: newHeadScreenPosition,
        oldTailScreenPosition: this.oldTailScreenPosition,
        newTailScreenPosition: newTailScreenPosition,
        oldHeadBufferPosition: this.oldHeadBufferPosition,
        newHeadBufferPosition: newHeadBufferPosition,
        oldTailBufferPosition: this.oldTailBufferPosition,
        newTailBufferPosition: newTailBufferPosition,
        textChanged: textChanged,
        wasValid: this.wasValid,
        isValid: isValid
      };
      this.oldHeadBufferPosition = newHeadBufferPosition;
      this.oldHeadScreenPosition = newHeadScreenPosition;
      this.oldTailBufferPosition = newTailBufferPosition;
      this.oldTailScreenPosition = newTailScreenPosition;
      this.wasValid = isValid;
      return this.emitter.emit('did-change', changeEvent);
    };

    return DisplayMarker;

  })();

}).call(this);
