<template>
  <header
    ref="headerRef"
    class="mc-header"
    :style="styleObject"
    :class="{
      'mc-header--shadow': showShadow,
      'mc-header--animate': animate,
      'mc-header--sticky': sticky,
      'mc-header--up': direction === 'up',
      'mc-header--down': direction === 'down',
    }"
  >
    <div class="mc-header__container">
      <MBreadcrumb
        v-if="hasBreadcrumb"
        class="mc-header__breadcrumb mc-breadcrumb--no-padding"
        :responsive="true"
        :items="items"
        @link-clicked="onLinkClicked"
      />
      <div class="mc-header__content">
        <div class="mc-header__content-main">
          <component
            :is="backHref ? 'a' : 'button'"
            v-if="hasBack"
            class="mc-header__back"
            :href="backHref ?? null"
            :type="!backHref ? 'button' : null"
            @click="!backHref && onClickBack()"
          >
            <MIcon name="ArrowBack24" class="mc-header__back-icon" />
            <span class="mc-header__back-label">
              {{ backButtonLabel }}
            </span>
          </component>
          <h1
            v-if="title"
            class="mc-header__title"
            :class="`mc-header__title--${size}`"
          >
            {{ title }}
          </h1>
          <!-- @slot Use this slot to manage the contents of the title -->
          <slot name="title" />
        </div>
        <div
          v-if="subTitle || $slots.subTitle || status || $slots.status"
          class="mc-header__content-aside"
          :class="{ 'can-navigate': hasBack }"
        >
          <slot name="subTitle">
            <span v-if="subTitle" class="mc-header__subtitle">
              {{ subTitle }}
            </span>
          </slot>
          <slot name="status">
            <MBadge v-if="status" :type="status.type">{{ status.text }}</MBadge>
          </slot>
        </div>
      </div>

      <div v-if="getActions" class="mc-header__actions">
        <div v-if="$slots.icons" class="mc-header__icons">
          <!-- @slot Use this slot to insert content for portal features such as help center and notifications -->
          <slot name="icons" />
        </div>
        <div v-if="$slots.selector" class="mc-header__selector">
          <!-- @slot Use this slot to insert content for context selection -->
          <slot name="selector" />
        </div>
      </div>
    </div>

    <div
      v-if="showTabs && hasTabs"
      class="mc-header__tabs mc-divider-top mc-divider-top--light"
    >
      <!-- @slot Use this slot to manage the contents of tabs -->
      <slot name="tabs">
        <MTab
          :tabs="tabs"
          :shadow="false"
          :active-index="selectedTabIndex"
          @tab-clicked="onTabClicked"
        />
      </slot>
    </div>
  </header>
</template>

<script setup>
import { computed, ref, toRefs, useSlots } from 'vue';

import MBadge from '../badge/MBadge.vue';
import MBreadcrumb from '../breadcrumb/MBreadcrumb.vue';
import MIcon from '../icon/MIcon.vue';
import MTab from '../tabs/MTab.vue';

import { useScrollDirection } from './composable/useScrollDirection';

/**
 * The `MHeader` component is the **Vue.js** implementation of the **Header** component of Mozaic Design System.<br/>
 */
const props = defineProps({
  /** Header's main title */
  title: {
    type: String,
    default: undefined,
  },
  /** Header subtitle */
  subTitle: {
    type: String,
    default: undefined,
  },
  /**
   * Object to define the properties of the **MBadge** component
   * @type {{ text: 'Text for status', type: 'information' }}
   */
  status: {
    type: Object,
    default: undefined,
  },
  /**
   * An array of objects to define the items of the **MBreadcrumb** component
   * @type {[{ text: 'Item text', href: '#itemlink', active: true }]}
   */
  items: {
    type: Array,
    default: () => [],
  },
  /**
   * An array of objects to define the items of the **MTab** component
   * @type {[{ text: 'Tab n°1 - Button' }, { text: 'Tab n°2 - Link', href: 'https://mozaic.adeo.cloud/' },]}
   */
  tabs: {
    type: Array,
    default: () => [],
  },
  /** Set selected tab by index. */
  selectedTabIndex: {
    type: Number,
    default: -1,
  },
  /** Display shadow to bottom of the header. */
  showShadow: {
    type: Boolean,
    default: false,
  },
  /** Show breadcrumb or not. */
  showBreadcrumb: {
    type: Boolean,
    default: false,
  },
  /** Show tabs or not. */
  showTabs: {
    type: Boolean,
    default: false,
  },
  /** Show back button or not. */
  showBack: {
    type: Boolean,
    default: false,
  },
  /** Animate when user scroll. */
  animate: {
    type: Boolean,
    default: false,
  },
  /** Set sticky position. */
  sticky: {
    type: Boolean,
    default: false,
  },
  /** The title size
   * @values s, m, l, xl
   */
  size: {
    type: String,
    default: 'm',
    validator: (value) => ['s', 'm', 'l', 'xl'].includes(value),
  },
  /** Label of the back button. Useful for accessibilty reason */
  backButtonLabel: {
    type: String,
    default: 'Back',
  },
  /** Href url of the back button */
  backHref: {
    type: String,
    default: undefined,
  },
  /**
   * Allows you to pass the z-index.
   */
  zIndex: {
    type: Number,
  },
});

const emit = defineEmits([
  'update:selectedTabIndex',
  'click-back',
  'link-clicked',
]);

const {
  showShadow,
  showBreadcrumb,
  showBack,
  showTabs,
  items,
  tabs,
  selectedTabIndex,
  animate,
  sticky,
} = toRefs(props);

const headerRef = ref();

const slots = useSlots();

const { direction } = useScrollDirection(headerRef, animate);

const hasTabs = computed(() => slots.tabs || tabs.value.length > 0);

const getActions = computed(() => slots.icons || slots.selector);

const hasBreadcrumb = computed(() => {
  return showBreadcrumb.value && items.value.length > 1;
});

const hasBack = computed(() => {
  return showBack.value && !hasBreadcrumb.value;
});

const styleObject = computed(() => {
  return {
    '--header-z-index': props.zIndex,
  };
});

const onLinkClicked = ($event) => {
  emit('link-clicked', $event);
};

function onTabClicked(_, e) {
  const tabItemIndex = tabs.value.findIndex((tab) => tab.id === e.id);

  if (tabItemIndex > -1 && selectedTabIndex.value !== tabItemIndex) {
    /**
     * Emits the value of the active tab
     */
    emit('update:selectedTabIndex', tabItemIndex);
  }
}

function onClickBack() {
  /**
   * Triggered each time the back button is clicked
   */
  emit('click-back');
}
</script>

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

@mixin set-container-padding() {
  padding-left: $mu200;
  padding-right: $mu200;

  @media (min-width: $screen-l) and (max-width: ($screen-xl - 1)) {
    padding-left: $mu300;
    padding-right: $mu300;
  }
}

.mc-header {
  @include set-font-face();

  background-color: $color-grey-000;
  z-index: var(--header-z-index, 5);

  &__container {
    @include set-container-padding();

    display: grid;
    padding-top: $mu050;
    padding-bottom: $mu100;
  }

  &__breadcrumb {
    grid-column: 1;
    grid-row: auto;
  }

  &__content {
    color: $color-font-darkest;
    grid-column: 1;
    grid-row: auto;
    padding-top: $mu050;

    &-main {
      display: flex;
      align-items: center;
      gap: $mu100;

      &:not(:only-child) {
        margin-bottom: $mu025;
      }
    }

    &-aside {
      display: flex;
      align-items: flex-start;
      flex-direction: column;
      gap: $mu050;
      padding-bottom: $mu050;

      &.can-navigate {
        padding-left: $mu300;
      }

      @include set-from-screen('l') {
        align-items: center;
        flex-direction: row;
        gap: $mu100;
        padding-bottom: 0;
      }
    }
  }

  &__back {
    @include unstyle-button();
    @include set-focus-floating-base();

    align-items: center;
    background-color: transparent;
    justify-content: center;
    color: currentColor;
    display: flex;
    height: $mu200;
    width: $mu200;

    &-icon {
      color: $color-grey-800;
      height: $mu150;
      width: $mu150;
    }

    &-label {
      @include visually-hidden();
    }

    &:focus {
      @include set-focus-floating();
    }
  }

  &__title {
    @include set-font-scale('08', 'm'); // 28px / 36px
    @include set-font-weight('semi-bold');

    margin-top: 0;
    margin-bottom: 0;

    &--s {
      @include set-font-scale('07', 'm'); // 23px / 32px
    }

    &--l {
      @include set-font-scale('09', 'm'); // 34px / 44px
    }

    &--xl {
      @include set-font-scale('10', 'm'); // 41px / 56px
    }
  }

  &__subtitle {
    @include set-font-scale('05', 'm'); // 16px / 22px
  }

  &__actions,
  &__icons {
    display: flex;
    gap: $mu150;
  }

  &__actions {
    align-items: flex-end;
    align-self: flex-start;
    grid-column: 1;
    grid-row: 1;
    justify-self: end;
    margin-bottom: $mu050;
    min-height: $mu250;

    @include set-from-screen('l') {
      grid-column: 2;
      grid-row: 1;
      margin-bottom: 0;
    }
  }

  &__selector {
    &:not(:only-child) {
      @include set-divider('left', 'light', '100%', 's');

      padding-left: px-to-rem(25);
      position: relative;
    }
  }

  &__tabs {
    @include set-container-padding();
  }

  // Modifiers
  &--shadow {
    @include set-box-shadow('s');
  }

  &--animate {
    left: 0;
    position: absolute;
    right: 0;
    transition: transform ease-out 0.4s;
  }

  &--sticky {
    position: sticky;
    top: 0;
  }

  &--up {
    transform: translateY(0);
  }

  &--down {
    transform: translateY(calc(-100% - 5px));
  }
}
</style>
