import BaseLayout from './baseLayout'

const Drawer = (($) => {

  /**
   * ------------------------------------------------------------------------
   * Constants
   * ------------------------------------------------------------------------
   */
  const NAME = 'drawer'
  const DATA_KEY = `bmd.${NAME}`
  const JQUERY_NAME = `bmd${NAME.charAt(0).toUpperCase() + NAME.slice(1)}`
  const JQUERY_NO_CONFLICT = $.fn[JQUERY_NAME]

  const Keycodes = {
    ESCAPE: 27
    //ENTER: 13,
    //SPACE: 32
  }

  const ClassName = {
    IN: 'in',
    DRAWER_IN: `bmd-drawer-in`,
    DRAWER_OUT: `bmd-drawer-out`,
    DRAWER: 'bmd-layout-drawer',
    CONTAINER: 'bmd-layout-container'
  }

  const Default = {
    focusSelector: `a, button, input`
  }

  /**
   * ------------------------------------------------------------------------
   * Class Definition
   * ------------------------------------------------------------------------
   */
  class Drawer extends BaseLayout {

    // $element is expected to be the trigger
    //  i.e. <button class="btn bmd-btn-icon" for="search" data-toggle="drawer" data-target="#my-side-nav-drawer" aria-expanded="false" aria-controls="my-side-nav-drawer">
    constructor($element, config) {
      super($element, $.extend(true, {}, Default, config))

      this.$toggles = $(`[data-toggle="drawer"][href="#${this.$element[0].id}"], [data-toggle="drawer"][data-target="#${this.$element[0].id}"]`)

      this._addAria()

      // click or escape on the backdrop closes the drawer
      this.$backdrop.keydown((ev) => {
        if (ev.which === Keycodes.ESCAPE) {
          this.hide()
        }
      }).click(() => {
        this.hide()
      })

      // escape on the drawer closes it
      this.$element.keydown((ev) => {
        if (ev.which === Keycodes.ESCAPE) {
          this.hide()
        }
      })

      // any toggle button clicks
      this.$toggles.click(() => {
        this.toggle()
      })
    }

    dispose() {
      super.dispose(DATA_KEY)
      this.$toggles = null
    }

    toggle() {
      if (this._isOpen()) {
        this.hide()
      } else {
        this.show()
      }
    }

    show() {
      if (this._isForcedClosed() || this._isOpen()) {
        return
      }

      this.$toggles.attr('aria-expanded', true)
      this.$element.attr('aria-expanded', true)
      this.$element.attr('aria-hidden', false)

      // focus on the first focusable item
      let $focusOn = this.$element.find(this.config.focusSelector)
      if ($focusOn.length > 0) {
        $focusOn.first().focus()
      }

      this.$container.addClass(ClassName.DRAWER_IN)
      // backdrop is responsively styled based on bmd-drawer-overlay, therefore style is none of our concern, simply add the marker class and let the scss determine if it should be displayed or not.
      this.$backdrop.addClass(ClassName.IN)
    }

    hide() {
      if (!this._isOpen()) {
        return
      }

      this.$toggles.attr('aria-expanded', false)
      this.$element.attr('aria-expanded', false)
      this.$element.attr('aria-hidden', true)

      this.$container.removeClass(ClassName.DRAWER_IN)
      this.$backdrop.removeClass(ClassName.IN)
    }


    // ------------------------------------------------------------------------
    // private

    _isOpen() {
      return this.$container.hasClass(ClassName.DRAWER_IN)
    }

    _isForcedClosed() {
      return this.$container.hasClass(ClassName.DRAWER_OUT)
    }

    _addAria() {
      let isOpen = this._isOpen()
      this.$element.attr('aria-expanded', isOpen)
      this.$element.attr('aria-hidden', isOpen)

      if (this.$toggles.length) {
        this.$toggles.attr('aria-expanded', isOpen)
      }
    }

    // ------------------------------------------------------------------------
    // static
    static _jQueryInterface(config) {
      return this.each(function () {
        let $element = $(this)
        let data = $element.data(DATA_KEY)

        if (!data) {
          data = new Drawer($element, config)
          $element.data(DATA_KEY, data)
        }
      })
    }
  }

  /**
   * ------------------------------------------------------------------------
   * jQuery
   * ------------------------------------------------------------------------
   */
  $.fn[JQUERY_NAME] = Drawer._jQueryInterface
  $.fn[JQUERY_NAME].Constructor = Drawer
  $.fn[JQUERY_NAME].noConflict = () => {
    $.fn[JQUERY_NAME] = JQUERY_NO_CONFLICT
    return Drawer._jQueryInterface
  }

  return Drawer

})(jQuery)

export default Drawer