 Point = require './point'
 Range = require './range'
 
+# Private: Manages the markers for a buffer.
 module.exports =
 class MarkerManager
   Serializable.includeInto(this)


  @delegatesMethods 'clipPosition', 'clipRange', toProperty: 'buffer'

  nextMarkerId: 1

  constructor: (@buffer, @markers) ->
    @intervals ?= @buildIntervals()
    @markers ?= {}

  buildIntervals: ->
    new IntervalSkipList
      compare: (a, b) -> a.compare(b)
      minIndex: new Point(-Infinity, -Infinity)
      maxIndex: new Point(Infinity, Infinity)

  serializeParams: ->
    markers = {}
    for id, marker of @markers
      markers[id] = marker.serialize()
    {markers}

  deserializeParams: (state) ->
    @intervals = @buildIntervals()
    for id, markerState of state.markers
      state.markers[id] = Marker.deserialize(markerState, manager: this)
    state

  markRange: (range, params) ->
    range = @clipRange(Range.fromObject(range, true)).freeze()
    params = Marker.extractParams(params)
    params.range = range
    @createMarker(params)

  markPosition: (position, options) ->
    @markRange(new Range(position, position), defaults({hasTail: false}, options))

  getMarker: (id) ->
    @markers[id]

  getMarkers: ->
    values(@markers)

  findMarkers: (params) ->
    params = clone(params)
    candidateIds = []

    @buffer.emit 'marker-created', marker
    marker

  # Private:
  removeMarker: (id) ->
    delete @markers[id]

  # Private:
  recordMarkerPatch: (patch) ->
    if @buffer.isTransacting()
      @buffer.history.recordNewPatch(patch)

  # Private: Updates markers based on the given {BufferPatch}.
  handleBufferChange: (patch) ->
    marker.handleBufferChange(patch) for id, marker of @markers

  # Private: Updates all markers based on a hash of patches indexed by marker id.
  applyPatches: (markerPatches, textChanged) ->
    for id, patch of markerPatches
      @getMarker(id)?.applyPatch(patch, textChanged)

  # Private:
  pauseChangeEvents: ->
    marker.pauseEvents('changed') for marker in @getMarkers()

  # Private:
  resumeChangeEvents: ->
    marker.resumeEvents('changed') for marker in @getMarkers()
