import { extend } from '../../../vue';
import { NAME_TOOLTIP_TEMPLATE } from '../../../constants/components';
import { EVENT_NAME_MOUSEENTER, EVENT_NAME_MOUSELEAVE, EVENT_NAME_FOCUSIN, EVENT_NAME_FOCUSOUT } from '../../../constants/events';
import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../../../constants/props';
import { isFunction } from '../../../utils/inspect';
import { makeProp } from '../../../utils/props';
import { scopedStyleMixin } from '../../../mixins/scoped-style';
import { BVPopper } from './bv-popper';

// --- Props ---

const props = {
  // Used only by the directive versions
  html: makeProp(PROP_TYPE_BOOLEAN, false),
  // Other non-reactive (while open) props are pulled in from BVPopper
  id: makeProp(PROP_TYPE_STRING)
};

// --- Main component ---

// @vue/component
const BVTooltipTemplate = /*#__PURE__*/extend({
  name: NAME_TOOLTIP_TEMPLATE,
  extends: BVPopper,
  mixins: [scopedStyleMixin],
  props,
  data() {
    // We use data, rather than props to ensure reactivity
    // Parent component will directly set this data
    return {
      title: '',
      content: '',
      variant: null,
      customClass: null,
      interactive: true
    };
  },
  computed: {
    templateType() {
      return 'tooltip';
    },
    templateClasses() {
      const {
        variant,
        attachment,
        templateType
      } = this;
      return [{
        // Disables pointer events to hide the tooltip when the user
        // hovers over its content
        noninteractive: !this.interactive,
        [`b-${templateType}-${variant}`]: variant,
        // `attachment` will come from BVToolpop
        [`bs-${templateType}-${attachment}`]: attachment
      }, this.customClass];
    },
    templateAttributes() {
      const {
        id
      } = this;
      return {
        // Apply attributes from root tooltip component
        ...this.bvParent.bvParent.$attrs,
        id,
        role: 'tooltip',
        tabindex: '-1',
        // Add the scoped style data attribute to the template root element
        ...this.scopedStyleAttrs
      };
    },
    templateListeners() {
      // Used for hover/focus trigger listeners
      return {
        mouseenter: /* istanbul ignore next */event => {
          this.$emit(EVENT_NAME_MOUSEENTER, event);
        },
        mouseleave: /* istanbul ignore next */event => {
          this.$emit(EVENT_NAME_MOUSELEAVE, event);
        },
        focusin: /* istanbul ignore next */event => {
          this.$emit(EVENT_NAME_FOCUSIN, event);
        },
        focusout: /* istanbul ignore next */event => {
          this.$emit(EVENT_NAME_FOCUSOUT, event);
        }
      };
    }
  },
  methods: {
    renderTemplate(h) {
      const {
        title
      } = this;

      // Title can be a scoped slot function
      const $title = isFunction(title) ? title({}) : title;

      // Directive versions only
      const domProps = this.html && !isFunction(title) ? {
        innerHTML: title
      } : {};
      return h('div', {
        staticClass: 'tooltip b-tooltip',
        class: this.templateClasses,
        attrs: this.templateAttributes,
        on: this.templateListeners
      }, [h('div', {
        staticClass: 'arrow',
        ref: 'arrow'
      }), h('div', {
        staticClass: 'tooltip-inner',
        domProps
      }, [$title])]);
    }
  }
});

export { BVTooltipTemplate, props };
