/**
 * --------------------------------------------
 * AdminLTE Treeview.js
 * License MIT
 * --------------------------------------------
 */

import $ from 'jquery'

/**
 * Constants
 * ====================================================
 */

const NAME = 'Treeview'
const DATA_KEY = 'lte.treeview'
const EVENT_KEY = `.${DATA_KEY}`
const JQUERY_NO_CONFLICT = $.fn[NAME]

const EVENT_EXPANDED = `expanded${EVENT_KEY}`
const EVENT_COLLAPSED = `collapsed${EVENT_KEY}`
const EVENT_LOAD_DATA_API = `load${EVENT_KEY}`

const SELECTOR_LI = '.nav-item'
const SELECTOR_LINK = '.nav-link'
const SELECTOR_TREEVIEW_MENU = '.nav-treeview'
const SELECTOR_OPEN = '.menu-open'
const SELECTOR_DATA_WIDGET = '[data-widget="treeview"]'

const CLASS_NAME_OPEN = 'menu-open'
const CLASS_NAME_IS_OPENING = 'menu-is-opening'
const CLASS_NAME_SIDEBAR_COLLAPSED = 'sidebar-collapse'

const Default = {
  trigger: `${SELECTOR_DATA_WIDGET} ${SELECTOR_LINK}`,
  animationSpeed: 300,
  accordion: true,
  expandSidebar: false,
  sidebarButtonSelector: '[data-widget="pushmenu"]'
}

/**
 * Class Definition
 * ====================================================
 */
class Treeview {
  constructor(element, config) {
    this._config = config
    this._element = element
  }

  // Public

  init() {
    $(`${SELECTOR_LI}${SELECTOR_OPEN} ${SELECTOR_TREEVIEW_MENU}${SELECTOR_OPEN}`).css('display', 'block')
    this._setupListeners()
  }

  expand(treeviewMenu, parentLi) {
    const expandedEvent = $.Event(EVENT_EXPANDED)

    if (this._config.accordion) {
      const openMenuLi = parentLi.siblings(SELECTOR_OPEN).first()
      const openTreeview = openMenuLi.find(SELECTOR_TREEVIEW_MENU).first()
      this.collapse(openTreeview, openMenuLi)
    }

    parentLi.addClass(CLASS_NAME_IS_OPENING)
    treeviewMenu.stop().slideDown(this._config.animationSpeed, () => {
      parentLi.addClass(CLASS_NAME_OPEN)
      $(this._element).trigger(expandedEvent)
    })

    if (this._config.expandSidebar) {
      this._expandSidebar()
    }
  }

  collapse(treeviewMenu, parentLi) {
    const collapsedEvent = $.Event(EVENT_COLLAPSED)

    parentLi.removeClass(`${CLASS_NAME_IS_OPENING} ${CLASS_NAME_OPEN}`)
    treeviewMenu.stop().slideUp(this._config.animationSpeed, () => {
      $(this._element).trigger(collapsedEvent)
      treeviewMenu.find(`${SELECTOR_OPEN} > ${SELECTOR_TREEVIEW_MENU}`).slideUp()
      treeviewMenu.find(SELECTOR_OPEN).removeClass(CLASS_NAME_OPEN)
    })
  }

  toggle(event) {
    const $relativeTarget = $(event.currentTarget)
    const $parent = $relativeTarget.parent()

    let treeviewMenu = $parent.find(`> ${SELECTOR_TREEVIEW_MENU}`)

    if (!treeviewMenu.is(SELECTOR_TREEVIEW_MENU)) {
      if (!$parent.is(SELECTOR_LI)) {
        treeviewMenu = $parent.parent().find(`> ${SELECTOR_TREEVIEW_MENU}`)
      }

      if (!treeviewMenu.is(SELECTOR_TREEVIEW_MENU)) {
        return
      }
    }

    event.preventDefault()

    const parentLi = $relativeTarget.parents(SELECTOR_LI).first()
    const isOpen = parentLi.hasClass(CLASS_NAME_OPEN)

    if (isOpen) {
      this.collapse($(treeviewMenu), parentLi)
    } else {
      this.expand($(treeviewMenu), parentLi)
    }
  }

  // Private

  _setupListeners() {
    const elementId = this._element.attr('id') !== undefined ? `#${this._element.attr('id')}` : ''
    $(document).on('click', `${elementId}${this._config.trigger}`, event => {
      this.toggle(event)
    })
  }

  _expandSidebar() {
    if ($('body').hasClass(CLASS_NAME_SIDEBAR_COLLAPSED)) {
      $(this._config.sidebarButtonSelector).PushMenu('expand')
    }
  }

  // Static

  static _jQueryInterface(config) {
    return this.each(function () {
      let data = $(this).data(DATA_KEY)
      const _options = $.extend({}, Default, $(this).data())

      if (!data) {
        data = new Treeview($(this), _options)
        $(this).data(DATA_KEY, data)
      }

      if (config === 'init') {
        data[config]()
      }
    })
  }
}

/**
 * Data API
 * ====================================================
 */

$(window).on(EVENT_LOAD_DATA_API, () => {
  $(SELECTOR_DATA_WIDGET).each(function () {
    Treeview._jQueryInterface.call($(this), 'init')
  })
})

/**
 * jQuery API
 * ====================================================
 */

$.fn[NAME] = Treeview._jQueryInterface
$.fn[NAME].Constructor = Treeview
$.fn[NAME].noConflict = function () {
  $.fn[NAME] = JQUERY_NO_CONFLICT
  return Treeview._jQueryInterface
}

export default Treeview
