(function() {
  var CompositeDisposable, DisplayMarker, DisplayMarkerLayer, Emitter, Point, Range, ref;

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

  DisplayMarker = require('./display-marker');

  Range = require('./range');

  Point = require('./point');

  module.exports = DisplayMarkerLayer = (function() {
    function DisplayMarkerLayer(displayLayer, bufferMarkerLayer, ownsBufferMarkerLayer) {
      this.displayLayer = displayLayer;
      this.bufferMarkerLayer = bufferMarkerLayer;
      this.ownsBufferMarkerLayer = ownsBufferMarkerLayer;
      this.id = this.bufferMarkerLayer.id;
      this.markersById = {};
      this.destroyed = false;
      this.emitter = new Emitter;
      this.subscriptions = new CompositeDisposable;
      this.markersWithDestroyListeners = new Set;
      this.subscriptions.add(this.bufferMarkerLayer.onDidUpdate(this.emitDidUpdate.bind(this)));
      this.subscriptions.add(this.bufferMarkerLayer.onDidDestroy(this.destroy.bind(this)));
    }


    /*
    Section: Lifecycle
     */

    DisplayMarkerLayer.prototype.destroy = function() {
      this.markersWithDestroyListeners.forEach(function(marker) {
        return marker.destroy();
      });
      this.destroyed = true;
      this.subscriptions.dispose();
      if (this.ownsBufferMarkerLayer) {
        this.bufferMarkerLayer.destroy();
      }
      return this.emitter.emit('did-destroy');
    };

    DisplayMarkerLayer.prototype.isDestroyed = function() {
      return this.destroyed;
    };


    /*
    Section: Event Subscription
     */

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

    DisplayMarkerLayer.prototype.onDidUpdate = function(callback) {
      return this.emitter.on('did-update', callback);
    };

    DisplayMarkerLayer.prototype.onDidCreateMarker = function(callback) {
      return this.bufferMarkerLayer.onDidCreateMarker((function(_this) {
        return function(bufferMarker) {
          return callback(_this.getMarker(bufferMarker.id));
        };
      })(this));
    };


    /*
    Section: Marker creation
     */

    DisplayMarkerLayer.prototype.markScreenRange = function(screenRange, options) {
      var bufferRange;
      screenRange = Range.fromObject(screenRange);
      bufferRange = this.displayLayer.translateScreenRange(screenRange, options);
      return this.createDisplayMarker(this.bufferMarkerLayer.markRange(bufferRange, options));
    };

    DisplayMarkerLayer.prototype.markScreenPosition = function(screenPosition, options) {
      var bufferPosition;
      screenPosition = Point.fromObject(screenPosition);
      bufferPosition = this.displayLayer.translateScreenPosition(screenPosition, options);
      return this.createDisplayMarker(this.bufferMarkerLayer.markPosition(bufferPosition, options));
    };

    DisplayMarkerLayer.prototype.markBufferRange = function(bufferRange, options) {
      bufferRange = Range.fromObject(bufferRange);
      return this.createDisplayMarker(this.bufferMarkerLayer.markRange(bufferRange, options));
    };

    DisplayMarkerLayer.prototype.markBufferPosition = function(bufferPosition, options) {
      return this.createDisplayMarker(this.bufferMarkerLayer.markPosition(Point.fromObject(bufferPosition), options));
    };

    DisplayMarkerLayer.prototype.createDisplayMarker = function(bufferMarker) {
      var displayMarker;
      displayMarker = new DisplayMarker(this, bufferMarker);
      this.markersById[displayMarker.id] = displayMarker;
      return displayMarker;
    };


    /*
    Section: Querying
     */

    DisplayMarkerLayer.prototype.getMarker = function(id) {
      var bufferMarker, displayMarker;
      if (displayMarker = this.markersById[id]) {
        return displayMarker;
      } else if (bufferMarker = this.bufferMarkerLayer.getMarker(id)) {
        return this.markersById[id] = new DisplayMarker(this, bufferMarker);
      }
    };

    DisplayMarkerLayer.prototype.getMarkers = function() {
      return this.bufferMarkerLayer.getMarkers().map((function(_this) {
        return function(arg) {
          var id;
          id = arg.id;
          return _this.getMarker(id);
        };
      })(this));
    };

    DisplayMarkerLayer.prototype.getMarkerCount = function() {
      return this.bufferMarkerLayer.getMarkerCount();
    };

    DisplayMarkerLayer.prototype.findMarkers = function(params) {
      params = this.translateToBufferMarkerLayerFindParams(params);
      return this.bufferMarkerLayer.findMarkers(params).map((function(_this) {
        return function(stringMarker) {
          return _this.getMarker(stringMarker.id);
        };
      })(this));
    };


    /*
    Section: Private
     */

    DisplayMarkerLayer.prototype.translateBufferPosition = function(bufferPosition, options) {
      return this.displayLayer.translateBufferPosition(bufferPosition, options);
    };

    DisplayMarkerLayer.prototype.translateBufferRange = function(bufferRange, options) {
      return this.displayLayer.translateBufferRange(bufferRange, options);
    };

    DisplayMarkerLayer.prototype.translateScreenPosition = function(screenPosition, options) {
      return this.displayLayer.translateScreenPosition(screenPosition, options);
    };

    DisplayMarkerLayer.prototype.translateScreenRange = function(screenRange, options) {
      return this.displayLayer.translateScreenRange(screenRange, options);
    };

    DisplayMarkerLayer.prototype.emitDidUpdate = function() {
      return this.emitter.emit('did-update');
    };

    DisplayMarkerLayer.prototype.notifyObserversIfMarkerScreenPositionsChanged = function() {
      var i, len, marker, ref1;
      ref1 = this.getMarkers();
      for (i = 0, len = ref1.length; i < len; i++) {
        marker = ref1[i];
        marker.notifyObservers(false);
      }
    };

    DisplayMarkerLayer.prototype.didDestroyMarker = function(marker) {
      return delete this.markersById[marker.id];
    };

    DisplayMarkerLayer.prototype.translateToBufferMarkerLayerFindParams = function(params) {
      var bufferMarkerLayerFindParams, endBufferRow, endScreenRow, key, startBufferRow, startScreenRow, value;
      bufferMarkerLayerFindParams = {};
      for (key in params) {
        value = params[key];
        switch (key) {
          case 'startBufferPosition':
            key = 'startPosition';
            break;
          case 'endBufferPosition':
            key = 'endPosition';
            break;
          case 'startScreenPosition':
            key = 'startPosition';
            value = this.displayLayer.translateScreenPosition(value);
            break;
          case 'endScreenPosition':
            key = 'endPosition';
            value = this.displayLayer.translateScreenPosition(value);
            break;
          case 'startBufferRow':
            key = 'startRow';
            break;
          case 'endBufferRow':
            key = 'endRow';
            break;
          case 'startScreenRow':
            key = 'startRow';
            value = this.displayLayer.translateScreenPosition(Point(value, 0)).row;
            break;
          case 'endScreenRow':
            key = 'endRow';
            value = this.displayLayer.translateScreenPosition(Point(value, Infinity)).row;
            break;
          case 'intersectsBufferRowRange':
            key = 'intersectsRowRange';
            break;
          case 'intersectsScreenRowRange':
            key = 'intersectsRowRange';
            startScreenRow = value[0], endScreenRow = value[1];
            startBufferRow = this.displayLayer.translateScreenPosition(Point(startScreenRow, 0)).row;
            endBufferRow = this.displayLayer.translateScreenPosition(Point(endScreenRow, Infinity)).row;
            value = [startBufferRow, endBufferRow];
            break;
          case 'containsBufferRange':
            key = 'containsRange';
            break;
          case 'containsBufferPosition':
            key = 'containsPosition';
            break;
          case 'containedInBufferRange':
            key = 'containedInRange';
            break;
          case 'containedInScreenRange':
            key = 'containedInRange';
            value = this.displayLayer.translateScreenRange(value);
            break;
          case 'intersectsBufferRange':
            key = 'intersectsRange';
            break;
          case 'intersectsScreenRange':
            key = 'intersectsRange';
            value = this.displayLayer.translateScreenRange(value);
        }
        bufferMarkerLayerFindParams[key] = value;
      }
      return bufferMarkerLayerFindParams;
    };

    return DisplayMarkerLayer;

  })();

}).call(this);
