import { BModal } from '../../../vendor/bootstrap-vue/src/components/modal/modal';
import { translate } from '../../../utils/i18n';
import { modalSizeOptions, modalButtonDefaults, focusableTags, COMMA } from '../../../utils/constants';
import { logWarning, focusFirstFocusableElement } from '../../../utils/utils';
import CloseButton from '../../shared_components/close_button/close_button';
import GlButton from '../button/button';
import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';

function validatorHelper(obj) {
  return Object.keys(obj).every(val => val === 'text' || val === 'attributes');
}
var script = {
  name: 'GlModal',
  components: {
    BModal,
    GlButton,
    CloseButton
  },
  inheritAttrs: false,
  model: {
    prop: 'visible',
    event: 'change'
  },
  props: {
    /**
     * Unique identifier for the modal. Used to control the modal programmatically.
     */
    modalId: {
      type: String,
      required: true
    },
    /**
     * HTML tag to use for the modal title. Options: 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'.
     */
    titleTag: {
      type: String,
      required: false,
      default: 'h4'
    },
    /**
     * HTML tag to use for the modal header. Default is 'div' for accessibility reasons.
     */
    headerTag: {
      type: String,
      required: false,
      default: 'div'
    },
    /**
     * Title text to display in the modal header.
     */
    title: {
      type: String,
      required: false,
      default: null
    },
    /**
     * Additional CSS class(es) to apply to the modal.
     */
    modalClass: {
      type: String,
      required: false,
      default: ''
    },
    /**
     * HTML tag to use for the modal footer. Default is 'div' for accessibility reasons.
     */
    footerTag: {
      type: String,
      required: false,
      default: 'div'
    },
    /**
     * Configuration object for the primary action button. Should contain 'text' and optionally 'attributes' properties.
     */
    actionPrimary: {
      type: Object,
      required: false,
      default: null,
      validator: obj => validatorHelper(obj)
    },
    /**
     * Configuration object for the secondary action button. Should contain 'text' and optionally 'attributes' properties.
     */
    actionSecondary: {
      type: Object,
      required: false,
      default: null,
      validator: obj => validatorHelper(obj)
    },
    /**
     * Configuration object for the cancel button. Should contain 'text' and optionally 'attributes' properties.
     */
    actionCancel: {
      type: Object,
      required: false,
      default: null,
      validator: obj => validatorHelper(obj)
    },
    /**
     * Size of the modal. Options: 'sm', 'md', 'lg'.
     */
    size: {
      type: String,
      required: false,
      default: modalSizeOptions.md,
      validator: val => Object.keys(modalSizeOptions).includes(val)
    },
    /**
     * The close button's label, it is used for the button's aria-label attribute.
     */
    dismissLabel: {
      type: String,
      required: false,
      default: () => translate('GlModal.closeButtonTitle', 'Close')
    },
    /**
     * Controls the visibility state of the modal.
     */
    visible: {
      type: Boolean,
      required: false,
      default: false
    },
    /**
     * Accessible label for the modal. Used for the aria-label attribute.
     */
    ariaLabel: {
      type: String,
      required: false,
      default: ''
    },
    /**
     * When true, prevents the modal from automatically focusing an element when shown.
     */
    noFocusOnShow: {
      type: Boolean,
      required: false,
      default: false
    }
  },
  computed: {
    shouldRenderModalOk() {
      // eslint-disable-next-line @gitlab/vue-prefer-dollar-scopedslots
      return Boolean(this.$slots['modal-ok']);
    },
    shouldRenderModalCancel() {
      // eslint-disable-next-line @gitlab/vue-prefer-dollar-scopedslots
      return Boolean(this.$slots['modal-cancel']);
    },
    shouldRenderModalFooter() {
      return Boolean(this.actionCancel || this.actionSecondary || this.actionPrimary ||
      // eslint-disable-next-line @gitlab/vue-prefer-dollar-scopedslots
      this.$slots['modal-footer']);
    }
  },
  mounted() {
    if (!this.ariaLabel && !this.title) {
      logWarning('Accessible name for modal missing. Please add title prop or aria-label.', {
        name: 'GlModal',
        element: this.$el
      });
    }
  },
  methods: {
    show() {
      this.$refs.modal.show();
    },
    hide() {
      this.$refs.modal.hide();
    },
    toggle() {
      this.$refs.modal.toggle();
    },
    ok() {
      this.$refs.modal.onOk();
    },
    cancel() {
      this.$refs.modal.onCancel();
    },
    close() {
      this.$refs.modal.onClose();
    },
    primary(event) {
      this.$emit('primary', event);
    },
    canceled(event) {
      this.$emit('canceled', event);
    },
    secondary(event) {
      this.$emit('secondary', event);
      if (!(event !== null && event !== void 0 && event.defaultPrevented)) {
        this.close();
      }
    },
    // set default variant button styling
    buttonBinding(prop, name) {
      if (!prop.attributes) {
        return modalButtonDefaults[name];
      }
      return prop.attributes;
    },
    setFocus() {
      if (this.noFocusOnShow) return;
      const btnElts = [...this.$refs.modal.$refs.modal.querySelectorAll('button')];
      const modalElts = [...this.$refs.modal.$refs.body.querySelectorAll(focusableTags.join(COMMA))];

      // Iterate over the array and if you find the close button,
      // move it to the end
      const closeBtnIndex = btnElts.findIndex(elt => {
        var _this$$refs$closeBut;
        return elt === ((_this$$refs$closeBut = this.$refs['close-button']) === null || _this$$refs$closeBut === void 0 ? void 0 : _this$$refs$closeBut.$el);
      });
      if (closeBtnIndex > -1) {
        btnElts.push(...btnElts.splice(closeBtnIndex, 1));
      }

      // ModalElts are the first choice, the btnElts are a backup
      focusFirstFocusableElement([...modalElts, ...btnElts]);
    }
  }
};

/* 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('b-modal',_vm._g(_vm._b({ref:"modal",attrs:{"id":_vm.modalId,"title-tag":_vm.titleTag,"size":_vm.size,"visible":_vm.visible,"aria-label":_vm.ariaLabel || _vm.title,"header-tag":_vm.headerTag,"footer-tag":_vm.footerTag,"lazy":"","modal-class":['gl-modal', _vm.modalClass]},on:{"shown":_vm.setFocus,"ok":_vm.primary,"cancel":_vm.canceled,"change":function($event){return _vm.$emit('change', $event)}},scopedSlots:_vm._u([{key:"default",fn:function(){return [_vm._t("default")]},proxy:true},{key:"modal-header",fn:function(){return [_vm._t("modal-header",function(){return [_c('h2',{staticClass:"modal-title"},[_vm._t("modal-title",function(){return [_vm._v(_vm._s(_vm.title))]})],2)]}),_vm._v(" "),_c('close-button',{ref:"close-button",attrs:{"label":_vm.dismissLabel},on:{"click":_vm.close}})]},proxy:true},(_vm.shouldRenderModalOk)?{key:"modal-ok",fn:function(){return [_vm._t("modal-ok")]},proxy:true}:null,(_vm.shouldRenderModalCancel)?{key:"modal-cancel",fn:function(){return [_vm._t("modal-cancel")]},proxy:true}:null,(_vm.shouldRenderModalFooter)?{key:"modal-footer",fn:function(){return [_vm._t("modal-footer",function(){return [(_vm.actionCancel)?_c('gl-button',_vm._b({staticClass:"js-modal-action-cancel",on:{"click":_vm.cancel}},'gl-button',_vm.buttonBinding(_vm.actionCancel, 'actionCancel'),false),[_vm._v("\n        "+_vm._s(_vm.actionCancel.text)+"\n      ")]):_vm._e(),_vm._v(" "),(_vm.actionSecondary)?_c('gl-button',_vm._b({staticClass:"js-modal-action-secondary",on:{"click":_vm.secondary}},'gl-button',_vm.buttonBinding(_vm.actionSecondary, 'actionSecondary'),false),[_vm._v("\n        "+_vm._s(_vm.actionSecondary.text)+"\n      ")]):_vm._e(),_vm._v(" "),(_vm.actionPrimary)?_c('gl-button',_vm._b({staticClass:"js-modal-action-primary",on:{"click":_vm.ok}},'gl-button',_vm.buttonBinding(_vm.actionPrimary, 'actionPrimary'),false),[_vm._v("\n        "+_vm._s(_vm.actionPrimary.text)+"\n      ")]):_vm._e()]})]},proxy:true}:null],null,true)},'b-modal',_vm.$attrs,false),_vm.$listeners))};
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__ = /*#__PURE__*/__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 { __vue_component__ as default };
