/* ========================================================================
 * Avvo UI - dropdown.js
 * ========================================================================
 * Forked from Bootstrap dropdown.js v3.3.1
 * http://getbootstrap.com/javascript/#dropdowns
 * ========================================================================
 * Copyright 2011-2014 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * ======================================================================== */

const $ = global.jQuery

// DROPDOWN CLASS DEFINITION
// =========================

const backdrop = '.dropdown-backdrop'
const toggle   = '[data-toggle="dropdown"]'
const Dropdown = function (element) {
  $(element).on('click.ui.dropdown', this.toggle)
}

Dropdown.VERSION = '4.0.0'

Dropdown.prototype.toggle = function (e) {
  const $this = $(this)

  if ($this.is('.disabled, :disabled')) {
    return
  }

  const $parent  = getParent($this)
  const isActive = $parent.hasClass('open')

  clearMenus()

  if (!isActive) {
    if ('ontouchstart' in document.documentElement) {
      // if mobile we use a backdrop because click events don't delegate
      $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
    }

    const relatedTarget = {
      relatedTarget: this,
    }
    const showEvent = $.Event('show.ui.dropdown', relatedTarget)
    $parent.trigger(showEvent)

    if (showEvent.isDefaultPrevented()) {
      return
    }

    $this
      .trigger('focus')
      .attr('aria-expanded', 'true')

    $parent
      .toggleClass('open')
      .trigger('shown.ui.dropdown', relatedTarget)
  }

  return false
}

Dropdown.prototype.keydown = function (e) {
  if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) {
    return
  }

  const $this = $(this)

  e.preventDefault()
  e.stopPropagation()

  if ($this.is('.disabled, :disabled')) {
    return
  }

  const $parent  = getParent($this)
  const isActive = $parent.hasClass('open')

  if ((!isActive && e.which !== 27) || (isActive && e.which === 27)) {
    if (e.which === 27) {
      $parent.find(toggle).trigger('focus')
    }
    return $this.trigger('click')
  }

  const desc = ' li:not(.divider):visible a'
  const $items = $parent.find(`[role="menu"]${desc}, [role="listbox"]${desc}`)

  if (!$items.length) {
    return
  }

  let index = $items.index(e.target)

  if (e.which === 38 && index > 0)                 index-- // up
  if (e.which === 40 && index < $items.length - 1) index++ // down
  if (!~index)                                     index = 0

  $items.eq(index).trigger('focus')
}

function clearMenus(e) {
  if (e && e.which === 3) {
    return
  }
  $(backdrop).remove()
  $(toggle).each(function () {
    const $this         = $(this)
    const $parent       = getParent($this)
    const relatedTarget = {
      relatedTarget: this,
    }

    if (!$parent.hasClass('open')) {
      return
    }

    const hideEvent = $.Event('hide.ui.dropdown', relatedTarget)
    $parent.trigger(hideEvent)

    if (hideEvent.isDefaultPrevented()) {
      return
    }

    $this.attr('aria-expanded', 'false')
    $parent.removeClass('open').trigger('hidden.ui.dropdown', relatedTarget)
  })
}

function getParent($this) {
  let selector = $this.attr('data-target')
  const href = $this.attr('href')

  if (!selector && /#[A-Za-z]/.test(href)) {
    selector = href.replace(/.*(?=#[^\s]*$)/, '')
  }

  const $parent = selector && $(selector)

  return $parent && $parent.length ? $parent : $this.parent()
}


// DROPDOWN PLUGIN DEFINITION
// ==========================

function Plugin(option) {
  return this.each(function () {
    const $this = $(this)
    let data  = $this.data('ui.dropdown')

    if (!data) {
      data = new Dropdown(this)
      $this.data('ui.dropdown', data)
    }
    if (typeof option === 'string') {
      data[option].call($this)
    }
  })
}

export function init() {
  const old = $.fn.dropdown

  $.fn.dropdown             = Plugin
  $.fn.dropdown.Constructor = Dropdown


  // DROPDOWN NO CONFLICT
  // ====================

  $.fn.dropdown.noConflict = function () {
    $.fn.dropdown = old
    return this
  }


  // APPLY TO STANDARD DROPDOWN ELEMENTS
  // ===================================

  $(document)
    .on('click.ui.dropdown.data-api', clearMenus)
    .on('click.ui.dropdown.data-api', '.dropdown form', (e) => {
      e.stopPropagation()
    })
    .on('click.ui.dropdown.data-api', toggle, Dropdown.prototype.toggle)
    .on('keydown.ui.dropdown.data-api', toggle, Dropdown.prototype.keydown)
    .on('keydown.ui.dropdown.data-api', '[role="menu"]', Dropdown.prototype.keydown)
    .on('keydown.ui.dropdown.data-api', '[role="listbox"]', Dropdown.prototype.keydown)
}
