<template>
  <div :class="['mc-tabs', classObject]">
    <ul
      v-if="type !== 'dropdown'"
      ref="tablist"
      class="mc-tabs__nav"
      role="tablist"
      :aria-label="description"
    >
      <li
        v-for="(tab, index) in tabs"
        :key="`tab-${index}`"
        class="mc-tabs__item"
        role="presentation"
      >
        <component
          :is="tab.href ? (tab.disabled ? 'span' : 'a') : 'button'"
          :id="tab.id"
          ref="tab"
          :href="tab.href ? (!tab.disabled ? tab.href : null) : null"
          :type="!tab.href ? 'button' : null"
          :disabled="!tab.href && tab.disabled ? true : null"
          class="mc-tabs__element"
          role="tab"
          :aria-selected="tab.active ? 'true' : 'false'"
          :class="setActiveClass(tab)"
          @click="
            manageTabs(
              $event.target,
              $event,
              Object.assign({ index: index }, tab)
            )
          "
        >
          <span class="mc-tabs__text">
            <MIcon v-if="tab.icon" :name="tab.icon" class="mc-tabs__icon" />
            {{ tab.text }}
          </span>
        </component>
      </li>
    </ul>
    <MSelect v-else v-bind="selectAttributes" :options="tabs" />
  </div>
</template>

<script>
import MSelect from '../select/MSelect.vue';
import MIcon from '../icon/MIcon.vue';

/**
 * > Tabs allow the user to navigate from a content to another within the same context. It keeps the user on the same page.
 *
 * The `MTab` component is the **Vue.js** implementation of the **Tabs** component of Mozaic Design System.<br/>
 * The full specification of this component is available in [the associated documentation](https://mozaic.adeo.cloud/components/tabs/).
 */
export default {
  name: 'MTab',
  components: {
    MIcon,
    MSelect,
  },
  props: {
    /**
     * An array of objects that allows you to provide all the data needed to generate the content for each tab
     * @type {[{ text: String, href: String, id: String, icon: MozaicIconName, active: Boolean, disabled: Boolean }]}
     */
    tabs: {
      type: Array,
      required: true,
      default() {
        return [];
      },
    },
    /**
     * Allows you to choose the type of display of the component. In "tabs" version or in "dropdown" version
     * @values tabs, dropdown
     * @see [Specific behaviour](https://mozaic.adeo.cloud/components/tabs/#specific-behaviour)
     */
    type: {
      type: String,
      default: 'tabs',
      validator: (value) => ['tabs', 'dropdown'].includes(value),
    },
    /**
     * A description indicating the purpose of the set of tabs. Useful for improving the accessibility of the component.
     * @see [Accessibility and semantic](https://mozaic.adeo.cloud/components/tabs/code/#accessibility-and-semantic)
     */
    description: {
      type: String,
      default: 'Tabs',
    },
    /**
     * Defines how the component will be aligned within the page
     * @values auto, full, centered
     * @see [Variations](https://mozaic.adeo.cloud/components/tabs/#variations)
     */
    align: {
      type: String,
      default: 'auto',
      validator: (value) => ['auto', 'full', 'centered'].includes(value),
    },
    /**
     * Allows to show or hide the divider. This value is set to true _(show)_ by default
     * @see [Variations](https://mozaic.adeo.cloud/components/tabs/#without-divider)
     */
    shadow: {
      type: Boolean,
      default: true,
    },
    /**
     * Allows to pass all desired attributes to the component in "Dropdown" version
     */
    selectAttributes: {
      type: Object,
      default: null,
    },
    /**
     * Allows to set the active tab. _(deprecated)_
     * @deprecated
     */
    activeIndex: {
      type: Number,
      default: 0,
    },
  },
  emits: ['tab-clicked'],
  data() {
    return {
      tablist: null,
    };
  },
  computed: {
    classObject() {
      return {
        'mc-tabs--full': this.align === 'full',
        'mc-tabs--full-centered': this.align === 'centered',
        'mc-tabs--dropdown': this.type === 'dropdown',
        'mc-tabs--no-shadow': !this.shadow,
      };
    },
  },
  watch: {
    activeIndex(newValue) {
      const tab = this.getTabFromIndex(newValue);
      if (tab && this.tabs[newValue]) {
        this.manageTabs(
          tab,
          null,
          Object.assign({ index: newValue }, this.tabs[newValue])
        );
      }
    },
  },
  mounted: function () {
    this.$nextTick(() => {
      if (this.type === 'tabs') {
        this.tablist = this.$refs.tablist;

        if (this.activeIndex) {
          const tab = this.getTabFromIndex(this.activeIndex);
          if (tab) {
            this.manageTabs(tab);
          }
        } else {
          const isActive = this.tabs.some((tab) =>
            Object.prototype.hasOwnProperty.call(tab, 'active')
          );
          if (!isActive) {
            const firstTab = this.tablist.querySelector('.mc-tabs__element');
            this.manageTabs(firstTab);
          }
        }
      }
    });
  },
  methods: {
    setActiveClass: function (tab) {
      const tabClasses = [];

      if (tab.active) {
        tabClasses.push('mc-tabs__element--selected');
      }

      if (tab.disabled) {
        tabClasses.push('mc-tabs__element--disabled');
      }

      return tabClasses;
    },
    manageTabs: function (el, e, tab) {
      if ((tab && tab.disabled) || !el) {
        return;
      }
      if (e) {
        /**
         * Triggers when a tab is clicked.
         *
         * - @arg {HTMLButtonElement} [currentTarget] - the HTML element of the tab clicked
         * - @arg {object} [tab] - a js object of values & datas of the tab clicked
         */
        this.$emit('tab-clicked', e.currentTarget, tab);
      }

      this.tablist.querySelectorAll('.mc-tabs__element').forEach((el) => {
        el.classList.remove('mc-tabs__element--selected');
        el.setAttribute('aria-selected', 'false');
      });

      el.classList.add('mc-tabs__element--selected');
      el.setAttribute('aria-selected', 'true');
    },
    getTabFromIndex: function (index) {
      if (
        this.tablist &&
        this.tablist.children[index] &&
        this.tablist.children[index].children[0]
      ) {
        return this.tablist.children[index].children[0];
      }
    },
  },
};
</script>

<style lang="scss">
@import 'settings-tools/all-settings';
@import 'components/c.tabs';
</style>
