       [@treeView, @treeViewEl] = []
 
   handleEvents: ->
-    # observe config
+    # keep config reference updated
     @disposables.add atom.config.onDidChange 'autohide-tree-view', ({newValue}) => @conf = clone newValue
+
+    # changes to these settings should trigger an update
     @disposables.add atom.config.onDidChange 'autohide-tree-view.pushEditor', => @update()
     @disposables.add atom.config.onDidChange 'autohide-tree-view.hiddenWidth', => @update()
     @disposables.add atom.config.onDidChange 'tree-view.showOnRightSide', => @update()

      @resize()
    .catch error

  show: (delay = @conf.showDelay, disableHoverEvents = false) ->
    @disableHoverEvents() if disableHoverEvents
    @storeFocusedElement()
    @treeView.scroller[0].style.display = ''
    @animate @treeView.list[0].clientWidth, delay
    .then (finished) =>
      @visible = true
      @treeView.focus() if finished

  hide: (delay = @conf.hideDelay) ->
    @visible = false
    @enableHoverEvents()
    @recoverFocus()
    @animate @conf.hiddenWidth, delay
    .then (finished) =>
      @treeView.scroller[0].style.display = 'none' if finished

  toggle: (disableHoverEvents = true) ->
    if @visible then @hide 0 else @show 0, disableHoverEvents

  resize: ->
    promiseNextTick.then() =>
      if @visible then @show 0  else @hide 0
    .catch error

  storeFocusedElement: ->
    @focusedElement = document.activeElement

  clearFocusedElement: ->
    @focusedElement = null

  recoverFocus: ->
    return unless @focusedElement?
    if typeof @focusedElement.focused is 'function'

      @focusedElement.focus()
    @clearFocusedElement()

  # enable hover events on the tree view
  enableHoverEvents: ->
    if @conf.showOn.match 'hover'
      @treeViewEl.classList.add 'autohide-hover'

  # disable hover events on the tree view
  disableHoverEvents: ->
    if @conf.showOn.match 'hover'
      @treeViewEl.classList.remove 'autohide-hover'

  # resolves true if animation finished, false if animation cancelled
  animate: (targetWidth, delay) ->
    # get the initial width of the element
    initialWidth = @treeViewEl.clientWidth
    # calculate the animation duration
    duration = Math.abs targetWidth - initialWidth / (@conf.animationSpeed or Infinity)

    # cancel any current animation
    if @currentAnimation? and @currentAnimation.playState isnt 'finished'
      @currentAnimation.cancel()
      @currentAnimation = null
      # if an animation was already occurring, this one
      # should trigger immediately
      delay = 0

    # explicitly set the elements initial width
    # @treeViewEl.style.width = "#{initialWidth}px"
    @treeViewEl.style.width = "#{initialWidth}px"
    new Promise (resolve) =>
      # no animation necessary
      if targetWidth is initialWidth
        return resolve true

      # cache the current animationPlayer so we can
      # cancel it as another animation begins
      @currentAnimation = animation = @treeViewEl.animate [
        {width: initialWidth}
        {width: targetWidth}
      ], {duration, delay}

      animation.onfinish = =>
        # if the animation we resolve with false
        if animation.playState isnt 'finished'
          return resolve false
        # prevent tree view from resetting its width to initialWidth
        @treeViewEl.style.width = "#{targetWidth}px"
        # remove the currentAnimation reference
        @currentAnimation = null
        resolve true
    .catch error
