<template>
  <a
    v-if="href"
    :href="href"
    class="mc-button"
    :class="classObject"
    :aria-label="ariaLabel"
  >
    <MIcon
      v-if="hasLeftIcon"
      :id="iconId"
      :class="classObjectIcon"
      :name="icon"
    />
    <span v-if="label" class="mc-button__label">
      {{ label }}
    </span>
    <MIcon
      v-if="hasRightIcon"
      :id="iconId"
      :class="classObjectIcon"
      :name="icon"
    />
  </a>
  <button
    v-else
    class="mc-button"
    :disabled="disabled"
    :class="classObject"
    :aria-label="ariaLabel"
    @click="onClick"
  >
    <MIcon
      v-if="hasLeftIcon"
      :id="iconId"
      :class="classObjectIcon"
      :name="icon"
    />
    <slot name="loader">
    <span v-if="label" class="mc-button__label">
      {{ label }}
    </span>
    </slot>
    <MIcon
      v-if="hasRightIcon"
      :id="iconId"
      :class="classObjectIcon"
      :name="icon"
    />
  </button>
</template>

<script>
import { useId } from 'vue';
import {
  responsiveModifiers,
  responsiveModifierValidators,
} from '../../utils/mozaicClasses';
import MIcon from '../icon/MIcon.vue';

/**
 * > Buttons are used to trigger actions. Their appearance is depending on the type of action required from the user, or the context.
 *
 * The `MButton` component is the **Vue.js** implementation of the **Button** component of Mozaic Design System.<br/>
 * The full specification of this component is available in [the associated documentation](https://mozaic.adeo.cloud/components/buttons/).
 */
export default {
  name: 'MButton',
  components: {
    MIcon,
  },
  props: {
    /**
     * The button label
     */
    label: {
      type: String,
      default: null,
    },
    /**
     * If set, changes the `<button>` tag to an `<a>` tag
     */
    href: {
      type: String,
      default: null,
    },
    /**
     * Allows you to set the colour theme of the button
     * @values solid, bordered, solid-neutral, bordered-neutral, solid-danger, bordered-danger, solid-secondary, bordered-secondary
     */
    theme: {
      type: String,
      default: null,
      validator: (value) =>
        [
          null,
          'solid',
          'bordered',
          'solid-neutral',
          'bordered-neutral',
          'solid-danger',
          'bordered-danger',
          'solid-primary-02',
          'bordered-primary-02'
        ].includes(value),
    },
    /**
     * Allows to define the button size
     * @values s, m, l
     * @see See [Available sizes](https://mozaic.adeo.cloud/components/buttons/code/#available-sizes)
     */
    size: {
      type: String,
      default: 'm',
      validator: (value) =>
        responsiveModifierValidators(value, [
          's',
          's@from-m',
          's@from-l',
          's@from-xl',
          's@from-xxl',
          'm',
          'm@from-m',
          'm@from-l',
          'm@from-xl',
          'm@from-xxl',
          'l',
          'l@from-m',
          'l@from-l',
          'l@from-xl',
          'l@from-xxl',
        ]),
    },
    /**
     * Allows to define the button width
     * @values fit, full
     * @see See [Width modifiers](https://mozaic.adeo.cloud/components/buttons/code/#width-modifiers)
     */
    width: {
      type: String,
      default: null,
      validator: (value) =>
        responsiveModifierValidators(value, [
          'fit',
          'fit@from-m',
          'fit@from-l',
          'fit@from-xl',
          'fit@from-xxl',
          'full',
          'full@from-m',
          'full@from-l',
          'full@from-xl',
          'full@from-xxl',
        ]),
    },
    /**
     * Allows to disabled the button
     */
    disabled: {
      type: Boolean,
      default: false,
    },
    /**
     * Allows to display an icon inside the button
     * @see [Variations with icons](https://mozaic.adeo.cloud/components/buttons/code/#variations-with-icons)
     */
    icon: {
      type: String,
      default: null,
    },
    /**
     * Define the icon position
     * @values left, right
     */
    iconPosition: {
      type: String,
      default: 'left',
      validator: (value) => ['left', 'right'].includes(value),
    },
    /**
     * To be used when using an icon only button.
     * Makes the button accessible.
     */
    ariaLabel: {
      type: String,
      default: null,
    },
  },
  emits: ['click'],
  setup() {
    return {
      id: useId()
    };
  },
  computed: {
    classObject() {
      const classes = [];

      if (this.theme) {
        classes.push(`mc-button--${this.theme}`);
      }

      if (this.size) {
        responsiveModifiers('mc-button', this.size, classes);
      }

      if (this.width) {
        responsiveModifiers('mc-button', this.width, classes);
      }

      if (!this.label) {
        classes.push('mc-button--square');
      }

      return classes;
    },
    iconId() {
      return `mc-button__${this.iconPosition}-icon-${this.id}`;
    },
    classObjectIcon() {
      return {
        'mc-button__icon': true,
        [`mc-button__icon--${this.iconPosition}`]: this.iconPosition,
      };
    },
    hasLeftIcon() {
      return this.icon && this.iconPosition === 'left';
    },
    hasRightIcon() {
      return this.icon && this.iconPosition === 'right';
    },
  },
  methods: {
    onClick(event) {
      /**
       * Triggered each time the button is clicked.
       */
      this.$emit('click', event);
    },
  },
};
</script>

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