#= require_self
#= require ./_position
#= require ./_templates

@CharacterEditor.Toolbar =
  init: (options, elem) ->
    @options = $.extend({}, @options, options)

    @_buttonTemplates = @_generateButtonTemplates(@options)

    @$elem = $(@_toolbarTemplate(@options))
    $(@options.viewSelector).append(@$elem)

    # this helps to not hide toolbar on selection (while toolbar button click)
    @keepToolbarVisible = false

    @_build()

    @_bind()

    @

  options: {}

  _build: ->
    @$toolbarButtons = @$elem.find('#character_editor_toolbar_buttons')
    @$anchorForm     = @$elem.find('#character_editor_toolbar_form_anchor')
    @$anchorInput    = @$anchorForm.children('input')

    @$toolbarButtons.show()
    @$anchorForm.hide()

  _bind: ->
    @_bindWindowResize()
    @_bindButtons()
    @_bindAnchorForm()
    @_bindSelect()

  _hide: ->
    @keepToolbarVisible = false
    @$elem.removeClass('character-editor-toolbar-active')
    @$toolbarButtons.removeClass()

  _show: ->
    timer = ''

    @$anchorForm.hide()

    # TODO: this can be optimized to do not change DOM
    html = ''
    $.each @options.buttons.split(' '), (i, key) => html += @_buttonTemplates[key]
    @$toolbarButtons.html(html)

    @$toolbarButtons.show()

    @$anchorInput.css('width', @$elem.width() - 40 - 12) # TODO: remove build in themes values

    @keepToolbarVisible = false

    clearTimeout(timer)

    timer = setTimeout ( =>
      if !@$elem.hasClass('character-editor-toolbar-active')
        @$elem.addClass('character-editor-toolbar-active')
    ), 100

  _bindSelect: ->
    if !@options.disableToolbar
      timer = ''
      toolbar = @

      $(@options.viewSelector).on 'mouseup keyup blur', (e) =>
        clearTimeout(timer)
        timer = setTimeout (-> toolbar._checkSelection()), @options.delay

  _bindWindowResize: ->
    timer = ''
    $(window).on 'resize', =>
      clearTimeout(timer)
      timer = setTimeout ( => if @$elem.hasClass('character-editor-toolbar-active') then @_setPosition() ), 100

  _getActiveEditor: ->
    $editorElement = $(@selection.getRangeAt(0).commonAncestorContainer).parents('[data-editor-element]')
    if $editorElement then $editorElement.data('editor') else false

  _checkSelection: ->
    if not @keepToolbarVisible
      @selection  = window.getSelection()

      if @selection.toString().trim() == ''
        return @_hide()

      activeEditor = @_getActiveEditor()
      if !activeEditor or activeEditor.options.disableToolbar
        return @_hide()

      selectionHtml = getSelectionHtml()
      selectionHtml = selectionHtml.replace(/<[\S]+><\/[\S]+>/gim, '')

      hasMultiParagraphs = selectionHtml.match(/<(p|h[0-6]|blockquote)>([\s\S]*?)<\/(p|h[0-6]|blockquote)>/g)

      if !@options.allowMultiParagraphSelection and hasMultiParagraphs
        return @_hide()

      @_setButtonStates()
      @_show()
      @_setPosition()

  _setButtonStates: ->
    $buttons = @$elem.find('button')
    $buttons.removeClass('character-editor-button-active')

    parentNode = @selection.anchorNode

    if !parentNode.tagName
      parentNode = @selection.anchorNode.parentNode

    while parentNode.tagName != undefined and @options.parentElements.indexOf(parentNode.tagName) == -1
      tag = parentNode.tagName.toLowerCase()
      @_activateButton(tag)
      parentNode = parentNode.parentNode

  _activateButton: (tag) ->
    $el = @$elem.find('[data-element="' + tag + '"]').first()
    if $el.length and !$el.hasClass('character-editor-button-active')
      $el.addClass('character-editor-button-active')

  _getSelectionData: (el) ->
    if el and el.tagName
      tagName = el.tagName.toLowerCase()

    while el and @options.parentElements.indexOf(tagName) == -1
      el = el.parentNode
      if el and el.tagName
        tagName = el.tagName.toLowerCase()

    return { el: el, tagName: tagName }

  _execFormatBlock: (el) ->
    selectionData = @_getSelectionData(@selection.anchorNode)

    # FF handles blockquote differently on formatBlock allowing nesting, we need to use outdent
    # https://developer.mozilla.org/en-US/docs/Rich-Text_Editing_in_Mozilla
    if el == 'blockquote' and selectionData.el and selectionData.el.parentNode.tagName.toLowerCase() == 'blockquote'
      return document.execCommand('outdent', false, null)

    if selectionData.tagName == el
      el = 'p'

    return document.execCommand('formatBlock', false, el)

  _execAction: (action, e) ->
    if action.indexOf('append-') > -1
     @_execFormatBlock(action.replace('append-', ''))
     @_setPosition()
     @_setButtonStates()

    else if action is 'anchor'
     @_triggerAnchorAction(e)

    else if action is 'image'
      document.execCommand('insertImage', false, window.getSelection())

    else
      document.execCommand(action, false, null)
      @_setPosition()

  _triggerAnchorAction: (e) ->
    if @selection.anchorNode.parentNode.tagName.toLowerCase() == 'a'
      document.execCommand('unlink', false, null)
    else
      if @$anchorForm.is(':visible') then @_show() else @_showAnchorForm()

  _showAnchorForm: ->
    @keepToolbarVisible = true

    @savedSelection = window.saveSelection()

    @$anchorForm.show()
    @$toolbarButtons.hide()

    @$anchorInput.focus()
    @$anchorInput.val('')

  _bindButtons: ->
    toolbar  = @

    triggerAction = (e) ->
      e.preventDefault()
      e.stopPropagation()

      $button = $(e.currentTarget)
      $button.toggleClass('character-editor-button-active')

      action = $button.attr('data-action')
      toolbar._execAction(action, e)

    $(document).on 'click', '#character_editor_toolbar_buttons button', triggerAction

  _setTargetBlank: ->
    el = window.getSelectionStart()

    if el.tagName.toLowerCase() == 'a'
      el.target = '_blank'
    else
      $(el).find('a').each (i, el) -> $(el).attr('target', '_blank')

  _createLink: (input) ->
    window.restoreSelection(@savedSelection)
    document.execCommand('createLink', false, @$anchorInput.val())

    if @options.targetBlank
      @_setTargetBlank()

    @_show()
    @$anchorInput.val('')

  _bindAnchorForm: ->
    @$anchorForm.on 'click', (e) ->
      e.stopPropagation()

    @$anchorInput.on 'keyup', (e) =>
      if e.keyCode == 13
        e.preventDefault()
        @_createLink()

    @$anchorInput.on 'blur', (e) =>
      @keepToolbarVisible = false

    @$anchorForm.find('a').on 'click', (e) =>
      e.preventDefault()
      window.restoreSelection(@savedSelection)

  destroy: ->
    $(@options.viewSelector).off 'mouseup keyup blur'
    $(window).off 'resize'
    @$anchorForm.off 'click'
    @$anchorForm.find('a').off 'click'
    @$anchorInput.on 'keyup blur'
    $(document).off 'click', '#character_editor_toolbar_buttons button'
    @$elem.remove()