<commit_before>class @AwardsHandler
  constructor: ->
    @aliases = emojiAliases()

    $(document)
      .off "click", ".js-add-award"
      .on "click", ".js-add-award", (event) =>
        event.stopPropagation()
        event.preventDefault()

        @showEmojiMenu $(event.currentTarget)

    $("html").on 'click', (event) ->
      if !$(event.target).closest(".emoji-menu").length
        if $(".emoji-menu").is(":visible")
          $('.js-add-award.is-active').removeClass 'is-active'
          $(".emoji-menu").removeClass "is-visible"

    $(document)
      .off "click", ".js-emoji-btn"
      .on "click", ".js-emoji-btn", @handleClick


  handleClick: (e) =>

    e.preventDefault()

    $emojiBtn = $(e.currentTarget)
    $addAwardBtn = $('.js-add-award.is-active')
    $votesBlock = $($addAwardBtn.closest('.js-award-holder').data('target'))

    if $addAwardBtn.length is 0
      $votesBlock = $emojiBtn.closest('.js-awards-block')
    else if $votesBlock.length is 0
      $votesBlock = $addAwardBtn.closest('.js-awards-block')

    $votesBlock.addClass 'js-awards-block'
    awardUrl = $votesBlock.data 'award-url'
    emoji = $emojiBtn.find('.icon').data('emoji')

    if emoji in [ 'thumbsup', 'thumbsdown' ]
      mutualVote = if emoji is 'thumbsup' then 'thumbsdown' else 'thumbsup'

      isAlreadyVoted = $("[data-emoji=#{mutualVote}]").parent().hasClass 'active'
      @addAward awardUrl, mutualVote if isAlreadyVoted

    @addAward awardUrl, emoji


  showEmojiMenu: ($addBtn) ->

    $menu = $('.emoji-menu')

    if $menu.length
      $holder = $addBtn.closest('.js-award-holder')

      if $menu.is ".is-visible"
        $addBtn.removeClass "is-active"
        $menu.removeClass "is-visible"
        $("#emoji_search").blur()
      else
        $addBtn.addClass "is-active"
        @positionMenu($menu, $addBtn)

        $menu.addClass "is-visible"
        $("#emoji_search").focus()
    else
      $addBtn.addClass 'is-loading is-active'
      url = $addBtn.data 'award-menu-url'

      @createEmojiMenu url, =>
        $addBtn.removeClass 'is-loading'
        $menu = $('.emoji-menu')
        @positionMenu($menu, $addBtn)
        @renderFrequentlyUsedBlock()

        setTimeout =>
          $menu.addClass 'is-visible'
          $('#emoji_search').focus()
          @setupSearch()
        , 200


  createEmojiMenu: (awardMenuUrl, callback) ->

    $.get awardMenuUrl, (response) =>
      $('body').append response
      callback()


  positionMenu: ($menu, $addBtn) ->
    position = $addBtn.data('position')

    # The menu could potentially be off-screen or in a hidden overflow element
    # So we position the element absolute in the body
    css =
      top: "#{$addBtn.offset().top + $addBtn.outerHeight()}px"

    if position? and position is 'right'
      css.left = "#{($addBtn.offset().left - $menu.outerWidth()) + 20}px"
      $menu.addClass "is-aligned-right"
    else
      css.left = "#{$addBtn.offset().left}px"
      $menu.removeClass "is-aligned-right"

    $menu.css(css)

  addAward: (awardUrl, emoji) ->
    emoji = @normilizeEmojiName(emoji)
    @postEmoji awardUrl, emoji, =>
      @addAwardToEmojiBar(emoji)

      $('.js-awards-block-current').removeClass 'js-awards-block-current'

    $(".emoji-menu").removeClass "is-visible"

  addAwardToEmojiBar: (emoji) ->
    @addEmojiToFrequentlyUsedList(emoji)

    emoji = @normilizeEmojiName(emoji)
    $emojiBtn = @findEmojiIcon(emoji).parent()

    if $emojiBtn.length > 0
      if @isActive($emojiBtn)
        @decrementCounter($emojiBtn, emoji)
      else
        counter = $emojiBtn.find('.js-counter')
        counter.text(parseInt(counter.text()) + 1)
        $emojiBtn.addClass("active")
        @addMeToUserList(emoji)
    else
      @createEmoji(emoji)

  isActive: ($emojiBtn) ->
    $emojiBtn.hasClass("active")

  decrementCounter: ($emojiBtn, emoji) ->
    isntNoteBody = $emojiBtn.closest('.note-body').length is 0
    counter = $('.js-counter', $emojiBtn)
    counterNumber = parseInt(counter.text())

    if !isntNoteBody
      # If this is a note body, we just hide the award emoji row like the initial state
      $emojiBtn.closest('.js-awards-block').addClass 'hidden'

    if counterNumber > 1
      counter.text(counterNumber - 1)
      @removeMeFromUserList($emojiBtn, emoji)
    else if (emoji == "thumbsup" || emoji == "thumbsdown") && isntNoteBody
      $emojiBtn.tooltip("destroy")
      counter.text('0')
      @removeMeFromUserList($emojiBtn, emoji)
    else
      $emojiBtn.tooltip("destroy")
      $emojiBtn.remove()

    $emojiBtn.removeClass("active")

  removeMeFromUserList: ($emojiBtn, emoji) ->
    award_block = $emojiBtn
    authors = award_block
      .attr("data-original-title")
      .split(", ")
    authors.splice(authors.indexOf("me"),1)
    award_block
      .closest(".js-emoji-btn")
      .attr("data-original-title", authors.join(", "))
    @resetTooltip(award_block)

  addMeToUserList: (emoji) ->
    award_block = @findEmojiIcon(emoji).parent()
    origTitle = award_block.attr("data-original-title").trim()
    users = []
    if origTitle
      users = origTitle.split(', ')
    users.push("me")
    award_block.attr("title", users.join(", "))
    @resetTooltip(award_block)

  resetTooltip: (award) ->
    award.tooltip("destroy")

    # "destroy" call is asynchronous and there is no appropriate callback on it, this is why we need to set timeout.
    setTimeout (->
      award.tooltip()
    ), 200


  createEmoji_: (emoji) ->

    emojiCssClass = @resolveNameToCssClass emoji

    buttonHtml = "<button class='btn award-control js-emoji-btn has-tooltip active' title='me' data-placement='bottom'>
      <div class='icon emoji-icon #{emojiCssClass}' data-emoji='#{emoji}'></div>
      <span class='award-control-text js-counter'>1</span>
    </button>"

    emoji_node = $(buttonHtml)<commit_msg>Fix award tooltip after voting.<commit_after>class @AwardsHandler
  constructor: ->
    @aliases = emojiAliases()

    $(document)
      .off "click", ".js-add-award"
      .on "click", ".js-add-award", (event) =>
        event.stopPropagation()
        event.preventDefault()

        @showEmojiMenu $(event.currentTarget)

    $("html").on 'click', (event) ->
      if !$(event.target).closest(".emoji-menu").length
        if $(".emoji-menu").is(":visible")
          $('.js-add-award.is-active').removeClass 'is-active'
          $(".emoji-menu").removeClass "is-visible"

    $(document)
      .off "click", ".js-emoji-btn"
      .on "click", ".js-emoji-btn", @handleClick


  handleClick: (e) =>

    e.preventDefault()

    $emojiBtn = $(e.currentTarget)
    $addAwardBtn = $('.js-add-award.is-active')
    $votesBlock = $($addAwardBtn.closest('.js-award-holder').data('target'))

    if $addAwardBtn.length is 0
      $votesBlock = $emojiBtn.closest('.js-awards-block')
    else if $votesBlock.length is 0
      $votesBlock = $addAwardBtn.closest('.js-awards-block')

    $votesBlock.addClass 'js-awards-block'
    awardUrl = $votesBlock.data 'award-url'
    emoji = $emojiBtn.find('.icon').data('emoji')

    if emoji in [ 'thumbsup', 'thumbsdown' ]
      mutualVote = if emoji is 'thumbsup' then 'thumbsdown' else 'thumbsup'

      isAlreadyVoted = $("[data-emoji=#{mutualVote}]").parent().hasClass 'active'
      @addAward awardUrl, mutualVote if isAlreadyVoted

    @addAward awardUrl, emoji


  showEmojiMenu: ($addBtn) ->

    $menu = $('.emoji-menu')

    if $menu.length
      $holder = $addBtn.closest('.js-award-holder')

      if $menu.is ".is-visible"
        $addBtn.removeClass "is-active"
        $menu.removeClass "is-visible"
        $("#emoji_search").blur()
      else
        $addBtn.addClass "is-active"
        @positionMenu($menu, $addBtn)

        $menu.addClass "is-visible"
        $("#emoji_search").focus()
    else
      $addBtn.addClass 'is-loading is-active'
      url = $addBtn.data 'award-menu-url'

      @createEmojiMenu url, =>
        $addBtn.removeClass 'is-loading'
        $menu = $('.emoji-menu')
        @positionMenu($menu, $addBtn)
        @renderFrequentlyUsedBlock()

        setTimeout =>
          $menu.addClass 'is-visible'
          $('#emoji_search').focus()
          @setupSearch()
        , 200


  createEmojiMenu: (awardMenuUrl, callback) ->

    $.get awardMenuUrl, (response) =>
      $('body').append response
      callback()


  positionMenu: ($menu, $addBtn) ->
    position = $addBtn.data('position')

    # The menu could potentially be off-screen or in a hidden overflow element
    # So we position the element absolute in the body
    css =
      top: "#{$addBtn.offset().top + $addBtn.outerHeight()}px"

    if position? and position is 'right'
      css.left = "#{($addBtn.offset().left - $menu.outerWidth()) + 20}px"
      $menu.addClass "is-aligned-right"
    else
      css.left = "#{$addBtn.offset().left}px"
      $menu.removeClass "is-aligned-right"

    $menu.css(css)

  addAward: (awardUrl, emoji) ->
    emoji = @normilizeEmojiName(emoji)
    @postEmoji awardUrl, emoji, =>
      @addAwardToEmojiBar(emoji)

      $('.js-awards-block-current').removeClass 'js-awards-block-current'

    $(".emoji-menu").removeClass "is-visible"

  addAwardToEmojiBar: (emoji) ->
    @addEmojiToFrequentlyUsedList(emoji)

    emoji = @normilizeEmojiName(emoji)
    $emojiBtn = @findEmojiIcon(emoji).parent()

    if $emojiBtn.length > 0
      if @isActive($emojiBtn)
        @decrementCounter($emojiBtn, emoji)
      else
        counter = $emojiBtn.find('.js-counter')
        counter.text(parseInt(counter.text()) + 1)
        $emojiBtn.addClass("active")
        @addMeToUserList(emoji)
    else
      @createEmoji(emoji)

  isActive: ($emojiBtn) ->
    $emojiBtn.hasClass("active")

  decrementCounter: ($emojiBtn, emoji) ->
    isntNoteBody = $emojiBtn.closest('.note-body').length is 0
    counter = $('.js-counter', $emojiBtn)
    counterNumber = parseInt(counter.text())

    if !isntNoteBody
      # If this is a note body, we just hide the award emoji row like the initial state
      $emojiBtn.closest('.js-awards-block').addClass 'hidden'

    if counterNumber > 1
      counter.text(counterNumber - 1)
      @removeMeFromUserList($emojiBtn, emoji)
    else if (emoji == "thumbsup" || emoji == "thumbsdown") && isntNoteBody
      $emojiBtn.tooltip("destroy")
      counter.text('0')
      @removeMeFromUserList($emojiBtn, emoji)
    else
      $emojiBtn.tooltip("destroy")
      $emojiBtn.remove()

    $emojiBtn.removeClass("active")


  getAwardTooltip: ($awardBlock) ->

    return $awardBlock.attr('data-original-title') or $awardBlock.attr('data-title')


  removeMeFromUserList: ($emojiBtn, emoji) ->

    awardBlock    = $emojiBtn
    originalTitle = @getAwardTooltip awardBlock

    authors = originalTitle.split ', '
    authors.splice authors.indexOf('me'), 1

    newAuthors = authors.join ', '

    awardBlock
      .closest '.js-emoji-btn'
      .removeData 'original-title'
      .removeData 'title'
      .attr 'data-original-title', newAuthors
      .attr 'data-title', newAuthors

    @resetTooltip(awardBlock)


  addMeToUserList: (emoji) ->

    awardBlock = @findEmojiIcon(emoji).parent()
    origTitle  = @getAwardTooltip awardBlock
    users      = []

    if origTitle
      users = origTitle.trim().split(', ')

    users.push('me')
    awardBlock.attr('title', users.join(", "))

    @resetTooltip(awardBlock)


  resetTooltip: (award) ->
    award.tooltip("destroy")

    # "destroy" call is asynchronous and there is no appropriate callback on it, this is why we need to set timeout.
    setTimeout (->
      award.tooltip()
    ), 200


  createEmoji_: (emoji) ->

    emojiCssClass = @resolveNameToCssClass emoji

    buttonHtml = "<button class='btn award-control js-emoji-btn has-tooltip active' title='me' data-placement='bottom'>
      <div class='icon emoji-icon #{emojiCssClass}' data-emoji='#{emoji}'></div>
      <span class='award-control-text js-counter'>1</span>
    </button>"

    emoji_node = $(buttonHtml)
{'fraction_non_alphanumeric': 0.15647677037284177, 'fraction_numerical': 0.0030027525231462173, 'mean_word_length': 2.9221458946679753, 'pattern_counts': {'":': 2, '<': 15, '<?xml version=': 0, '>': 60, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6976841', 'n_tokens_mistral': 4102, 'n_tokens_neox': 4057, 'n_words': 760}