module.exports =
class OverlayManager
  constructor: (@container) ->
    @overlays = {}

  render: (props) ->
    {presenter, editor, overlayDecorations} = props
    lineHeight = presenter.getLineHeight()

    existingDecorations = null
    for markerId, {headPixelPosition, tailPixelPosition, decorations} of overlayDecorations
      for decoration in decorations
        pixelPosition =
          if decoration.position is 'tail' then tailPixelPosition else headPixelPosition

        @renderOverlay(editor, decoration, pixelPosition, lineHeight)

        existingDecorations ?= {}
        existingDecorations[decoration.id] = true

    for id, overlay of @overlays
      unless existingDecorations? and id of existingDecorations
        @container.removeChild(overlay)
        delete @overlays[id]

    return

  renderOverlay: (editor, decoration, pixelPosition, lineHeight) ->
    item = atom.views.getView(decoration.item)
    unless overlay = @overlays[decoration.id]
      overlay = @overlays[decoration.id] = document.createElement('atom-overlay')
      overlay.appendChild(item)
      @container.appendChild(overlay)

    itemWidth = item.offsetWidth
    itemHeight = item.offsetHeight

    left = pixelPosition.left
    if left + itemWidth - editor.getScrollLeft() > editor.getWidth() and left - itemWidth >= editor.getScrollLeft()
      left -= itemWidth

    top = pixelPosition.top + lineHeight
    if top + itemHeight - editor.getScrollTop() > editor.getHeight() and top - itemHeight - lineHeight >= editor.getScrollTop()
      top -= itemHeight + lineHeight

    overlay.style.top = top + 'px'
    overlay.style.left = left + 'px'

module.exports =
class OverlayManager
  constructor: (@container) ->
    @overlayNodesById = {}

  render: (props) ->
    {presenter} = props

    for decorationId, {pixelPosition, item} of presenter.state.content.overlays
      @renderOverlay(presenter, decorationId, item, pixelPosition)

    for id, overlayNode of @overlayNodesById
      unless presenter.state.content.overlays.hasOwnProperty(id)
        overlayNode.remove()
        delete @overlayNodesById[id]

    return

  renderOverlay: (presenter, decorationId, item, pixelPosition) ->
    item = atom.views.getView(item)
    unless overlayNode = @overlayNodesById[decorationId]
      overlayNode = @overlayNodesById[decorationId] = document.createElement('atom-overlay')
      overlayNode.appendChild(item)
      @container.appendChild(overlayNode)

    itemWidth = item.offsetWidth
    itemHeight = item.offsetHeight


    {scrollTop} = presenter.state
    {scrollLeft} = presenter.state.content

    left = pixelPosition.left
    if left + itemWidth - scrollLeft > presenter.getClientWidth() and left - itemWidth >= scrollLeft
      left -= itemWidth

    top = pixelPosition.top + presenter.getLineHeight()
    if top + itemHeight - scrollTop > presenter.getClientHeight() and top - itemHeight - presenter.getLineHeight() >= scrollTop
      top -= itemHeight + presenter.getLineHeight()

    overlayNode.style.top = top + 'px'
    overlayNode.style.left = left + 'px'

Use presenter for rendering overlay decorations
Use presenter for rendering overlay decorations

We’re still doing some sync DOM reads and computation in the view that
should eventually be made async and moved into the presenter, but I’m
going to leave it alone for now.
