/**
 * --------------------------------------------
 * 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

    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]()
            }
        })
    }

    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)
        })
    }

    // Private

    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)
        }
    }

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

    // Static

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

/**
 * 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
