import uniqueId from 'lodash/uniqueId';
import GlDropdownItem from '../dropdown/dropdown_item';
import { tokensValidator } from './helpers';
import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';

var script = {
  name: 'GlTokenSelectorDropdown',
  components: {
    GlDropdownItem
  },
  props: {
    show: {
      type: Boolean,
      required: true
    },
    menuClass: {
      type: [String, Array, Object],
      required: false,
      default: ''
    },
    loading: {
      type: Boolean,
      required: false,
      default: false
    },
    dropdownItems: {
      type: Array,
      // All items need to have an `id` key
      validator: tokensValidator,
      required: true
    },
    inputText: {
      type: String,
      required: true
    },
    userDefinedTokenCanBeAdded: {
      type: Boolean,
      required: true
    },
    componentId: {
      type: String,
      required: true
    },
    registerDropdownEventHandlers: {
      type: Function,
      required: true
    },
    registerResetFocusedDropdownItem: {
      type: Function,
      required: true
    }
  },
  data() {
    return {
      focusedDropdownItemIndex: 0
    };
  },
  computed: {
    userDefinedToken() {
      return {
        id: uniqueId('user-defined-token'),
        name: this.inputText
      };
    },
    dropdownLength() {
      // Adds an additional dropdown item for the 'Add ... dropdown' item
      return this.userDefinedTokenCanBeAdded ? this.dropdownItems.length : this.dropdownItems.length - 1;
    },
    focusedLastDropdownItem() {
      return this.focusedDropdownItemIndex === this.dropdownLength;
    },
    focusedUserDefinedToken() {
      // User defined tokens are always the last in the list
      return this.userDefinedTokenCanBeAdded && this.focusedLastDropdownItem;
    },
    focusedDropdownItem() {
      if (this.focusedUserDefinedToken) {
        return this.userDefinedToken;
      }
      return this.dropdownItems[this.focusedDropdownItemIndex];
    }
  },
  watch: {
    focusedDropdownItem(newValue, oldValue) {
      if ((newValue === null || newValue === void 0 ? void 0 : newValue.id) !== (oldValue === null || oldValue === void 0 ? void 0 : oldValue.id)) {
        this.$emit('input', newValue);
        if (!newValue) {
          return;
        }
        const dropdownItemRef = this.getDropdownItemRef(newValue);
        if (dropdownItemRef !== null && dropdownItemRef !== void 0 && dropdownItemRef.$el) {
          dropdownItemRef.$el.scrollIntoView({
            block: 'nearest',
            inline: 'end'
          });
        }
      }
    }
  },
  created() {
    this.registerDropdownEventHandlers({
      handleUpArrow: this.handleUpArrow,
      handleDownArrow: this.handleDownArrow,
      handleHomeKey: this.handleHomeKey,
      handleEndKey: this.handleEndKey
    });
    this.registerResetFocusedDropdownItem(this.resetFocusedDropdownItem);
    this.$emit('input', this.focusedDropdownItem);
  },
  methods: {
    handleDropdownItemClick(dropdownItem) {
      this.$emit('dropdown-item-click', dropdownItem);
    },
    handleMousedown(dropdownItem) {
      // `event.relatedTarget` returns `null` on Safari because buttons are not focused on click (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#Clicking_and_focus)
      // Because of this we need to manually focus on the button. We do this in `mousedown` because it is fired before the `blur` event
      const dropdownItemRef = this.getDropdownItemRef(dropdownItem);
      if (dropdownItemRef !== null && dropdownItemRef !== void 0 && dropdownItemRef.$el) {
        dropdownItemRef.$el.querySelector('button').focus();
      }
    },
    handleUpArrow() {
      if (!this.show) {
        return;
      }

      // First dropdown item has been reached
      if (this.focusedDropdownItemIndex === 0) {
        return;
      }
      this.focusPrevDropdownItem();
    },
    handleDownArrow() {
      if (!this.show) {
        this.$emit('show');
        return;
      }

      // Last dropdown item has been reached
      if (this.focusedLastDropdownItem) {
        return;
      }
      this.focusNextDropdownItem();
    },
    handleHomeKey(event) {
      event.preventDefault();
      this.focusFirstDropdownItem();
    },
    handleEndKey(event) {
      event.preventDefault();
      this.focusLastDropdownItem();
    },
    focusLastDropdownItem() {
      this.focusedDropdownItemIndex = this.dropdownLength;
    },
    focusFirstDropdownItem() {
      this.focusedDropdownItemIndex = 0;
    },
    focusNextDropdownItem() {
      this.focusedDropdownItemIndex += 1;
    },
    focusPrevDropdownItem() {
      this.focusedDropdownItemIndex -= 1;
    },
    resetFocusedDropdownItem() {
      this.focusedDropdownItemIndex = 0;
    },
    dropdownItemIsFocused(dropdownItem) {
      if (!this.focusedDropdownItem) {
        return false;
      }
      return dropdownItem.id === this.focusedDropdownItem.id;
    },
    getDropdownItemRef(dropdownItem) {
      var _this$$refs$dropdownI;
      if (this.focusedUserDefinedToken) {
        return this.$refs[this.userDefinedToken.id];
      }
      return (_this$$refs$dropdownI = this.$refs.dropdownItems) === null || _this$$refs$dropdownI === void 0 ? void 0 : _this$$refs$dropdownI.find(ref => ref.$attrs['data-dropdown-item-id'] === dropdownItem.id);
    },
    dropdownItemIdAttribute(dropdownItem) {
      return dropdownItem ? `${this.componentId}-dropdown-item-${dropdownItem.id}` : null;
    }
  }
};

/* script */
const __vue_script__ = script;

/* template */
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"dropdown b-dropdown gl-dropdown gl-relative",class:{ show: _vm.show }},[_c('ul',{ref:"dropdownMenu",staticClass:"dropdown-menu gl-absolute",class:[{ show: _vm.show }, _vm.menuClass],attrs:{"role":"menu","aria-activedescendant":_vm.dropdownItemIdAttribute(_vm.focusedDropdownItem)}},[(_vm.loading)?_c('gl-dropdown-item',{attrs:{"disabled":""}},[_vm._t("loading-content",function(){return [_vm._v("Searching...")]})],2):_vm._e(),_vm._v(" "),_vm._l((_vm.dropdownItems),function(dropdownItem){return _c('gl-dropdown-item',{key:dropdownItem.id,ref:"dropdownItems",refInFor:true,attrs:{"id":_vm.dropdownItemIdAttribute(dropdownItem),"data-dropdown-item-id":dropdownItem.id,"active":_vm.dropdownItemIsFocused(dropdownItem),"active-class":"is-focused","tabindex":"-1"},on:{"click":function($event){return _vm.handleDropdownItemClick(dropdownItem)}}},[_c('div',{staticClass:"-gl-mx-4 -gl-my-3 gl-px-4 gl-py-3",on:{"mousedown":function($event){return _vm.handleMousedown(dropdownItem)}}},[_vm._t("dropdown-item-content",function(){return [_vm._v("\n          "+_vm._s(dropdownItem.name)+"\n        ")]},{"dropdownItem":dropdownItem})],2)])}),_vm._v(" "),(_vm.userDefinedTokenCanBeAdded)?_c('gl-dropdown-item',{ref:_vm.userDefinedToken.id,attrs:{"id":_vm.dropdownItemIdAttribute(_vm.userDefinedToken),"data-dropdown-item-id":_vm.userDefinedToken.id,"active":_vm.dropdownItemIsFocused(_vm.userDefinedToken),"active-class":"is-focused","tabindex":"-1"},on:{"click":function($event){return _vm.handleDropdownItemClick(_vm.userDefinedToken)}}},[_c('div',{staticClass:"-gl-mx-4 -gl-my-3 gl-px-4 gl-py-3",on:{"mousedown":function($event){return _vm.handleMousedown(_vm.userDefinedToken)}}},[_vm._t("user-defined-token-content",function(){return [_vm._v("\n          Add \""+_vm._s(_vm.inputText)+"\"\n        ")]},{"inputText":_vm.inputText})],2)]):(!_vm.dropdownItems.length)?_c('gl-dropdown-item',{attrs:{"disabled":""}},[_vm._t("no-results-content",function(){return [_vm._v("No matches found")]})],2):_vm._e(),_vm._v(" "),_vm._t("dropdown-footer")],2)])};
var __vue_staticRenderFns__ = [];

  /* style */
  const __vue_inject_styles__ = undefined;
  /* scoped */
  const __vue_scope_id__ = undefined;
  /* module identifier */
  const __vue_module_identifier__ = undefined;
  /* functional template */
  const __vue_is_functional_template__ = false;
  /* style inject */
  
  /* style inject SSR */
  
  /* style inject shadow dom */
  

  
  const __vue_component__ = __vue_normalize__(
    { render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ },
    __vue_inject_styles__,
    __vue_script__,
    __vue_scope_id__,
    __vue_is_functional_template__,
    __vue_module_identifier__,
    false,
    undefined,
    undefined,
    undefined
  );

export default __vue_component__;
