<template>
  <nav
    class="mc-sidebar"
    :style="styleObject"
    :class="{ 'is-open': localOpen, 'is-close': !localOpen }"
    aria-labelledby="mc-sidebar__trigger"
    :aria-expanded="localOpen"
  >
    <div class="mc-sidebar__container" :class="{ 'has-bottom-panel': user }">
      <button
        id="mc-sidebar__trigger"
        type="button"
        class="mc-sidebar__trigger"
        aria-label="Open / Close menu"
        @click="toggleSidebar"
      >
        <span class="mc-sidebar__trigger__container">
          <MIcon
            v-if="!localOpen"
            name="ArrowDoubleArrowRight24"
            color="#ffffff"
          />
          <MIcon v-else name="ArrowDoubleArrowLeft24" color="#ffffff" />
        </span>
      </button>
      <MSidebarSegment
        v-if="home"
        :data="home"
        :with-tooltip="withTooltip"
        :selected="localSelected"
        :open="localOpen"
        @code-changed="codeChanged"
      />
      <MSidebarSeparator :open="localOpen" />
      <MSidebarSection
        :features="features"
        :open="localOpen"
        :with-tooltip="withTooltip"
        :selected="localSelected"
        @code-changed="codeChanged"
        @toggle-sidebar="toggleSidebar"
      />
      <div v-if="utilities" class="mc-sidebar__utilities">
        <div v-for="(section, i) in utilities" :key="i">
          <MSidebarSeparator :open="localOpen" />
          <ul>
            <li
              v-for="(feature, j) in section"
              :key="j"
              class="mc-sidebar__utilities__item"
            >
              <MSidebarSegment
                :data="feature"
                :with-tooltip="withTooltip"
                :selected="localSelected"
                :open="localOpen"
                @code-changed="codeChanged"
              />
            </li>
          </ul>
        </div>
      </div>
    </div>
    <MSidebarNavigationUser
      v-if="user"
      :user-features="userFeatures"
      :selected="localSelected"
      :open="localOpen"
      :user="user"
      @toggle-sidebar="toggleSidebar"
      @code-changed="codeChanged"
    />
  </nav>
</template>

<script>
import { computed } from 'vue';
import { selectFeature } from './helper';
import MIcon from '../icon/MIcon.vue';
import MSidebarSegment from './MSidebarSegment.vue';
import MSidebarSeparator from './MSidebarSeparator.vue';
import MSidebarSection from './MSidebarSection.vue';
import MSidebarNavigationUser from './MSidebarNavigationUser.vue';

/**
 * > A Sidebar is a component that allows navigation from a bar on the side of the screen.
 *
 * The `MSidebar` component is the **Vue.js** implementation of the **Sidebar** component of Mozaic Design System.<br/>
 * The full specification of this component is available in [the associated documentation](https://mozaic.adeo.cloud/components/sidebar/).
 */
export default {
  name: 'MSidebar',
  components: {
    MIcon,
    MSidebarNavigationUser,
    MSidebarSection,
    MSidebarSeparator,
    MSidebarSegment,
  },
  provide() {
    return {
      selected: computed(() => this.localSelected),
      open: computed(() => this.localOpen),
      home: computed(() => this.home),
      features: computed(() => this.features),
      userFeatures: computed(() => this.userFeatures),
      utilities: computed(() => this.utilities),
    };
  },
  props: {
    /**
     * An object that defines the ["Portal" item](https://tinyurl.com/figma-sidebar-portal). Works like a "Home" button. Allows the user to return to the portal homepage.
     * @type {{ label: string, code: string, icon: string, href?: string, target?: string, route?: string }}
     */
    home: {
      type: Object,
      default: null,
    },
    /**
     * An array of objects that defines [Features items & subitems](https://tinyurl.com/figma-sidebar-features). Often used for the different main pages of the application.
     * @type {[{ label: string, code: string, icon: string, href?: string, target?: string, route?: string, items: [label: string, code: string, href?: string, target?: string, route?: string, disabled?: boolean] }]}
     */
    features: {
      type: Array,
      default: () => [],
    },
    /**
     * A multidimensional array for creating sections placed under the "features".<br/>
     * Each nested array creates a new section demarcated by a separator.<br/>
     * Each object in a nested array defines an item in that section.
     * @type {[[{ label: string, code: string, icon: string, href?: string, target?: string, route?: string }]]}
     */
    utilities: {
      type: Array,
      default: () => [],
    },
    /**
     * Allows to display a user on the bottom of the sidebar. Often used to display the connected user.
     * @type {{ lastName: string, firstName: string, title: string, imageSrc?: string, imageBase64?: string }}
     */
    user: {
      type: Object,
      default: null,
    },
    /**
     * User features allow you to add actions in relation to the user. They will be displayed in a list that appears when the user is clicked on.
     * @type {[label: string, code: string, href?: string, target?: string, route?: string, disabled?: boolean]}
     */
    userFeatures: {
      type: Array,
      default: () => [],
    },
    /**
     * This object will allow to keep the selection on the 3 levels that the navbar proposes
     * @type {{ lv0: {code: string, label: string, items: Array}, lv1: {code: string, label: string, items: Array}, lv2: {code: string, label: string, items: Array} }}
     */
    modelValue: {
      type: Object,
      default: () => ({ lv0: {}, lv1: {}, lv2: {} }),
    },
    /**
     * Displays the labels of items in a tooltip when the sidebar is closed.
     */
    withTooltip: {
      type: Boolean,
      default: false,
    },
    /**
     * Allows to define if the navbar should be opened or not
     */
    open: {
      type: Boolean,
      default: false,
    },
    /**
     * Allows you to close the sidebar by clicking on the content
     */
    closedToClick: {
      type: Boolean,
      default: false,
    },
    /**
     * Allows you pass the z-index
     */
    zIndex: {
      type: Number,
    },
  },
  emits: ['update:modelValue', 'open-status', 'code-change'],
  data() {
    return {
      localOpen: this.open ?? false,
      localSelected: this.modelValue,
    };
  },
  computed: {
    styleObject() {
      return {
        '--sidebar-z-index': this.zIndex,
      };
    },
  },
  watch: {
    open() {
      this.localOpen = this.open;
    },
    modelValue() {
      this.localSelected = this.modelValue;
    },
  },
  methods: {
    toggleSidebar() {
      this.localOpen = !this.localOpen;

      /**
       * Emits the component's open state value
       */
      this.$emit('open-status', this.localOpen);
    },
    codeChanged(code) {
      this.onChange(
        selectFeature(
          this.features,
          this.utilities,
          this.userFeatures,
          this.home,
          code,
        ),
      );

      if (this.localOpen && this.closedToClick) {
        this.toggleSidebar();
      }
      this.$emit('code-change', code);
    },
    onChange(selected) {
      this.localSelected = selected;

      /**
       * Triggered each time an item that does not have sub-items is clicked.
       * - @arg {object} - an object in the form of `{lv0: {}, lv1: {}, lv2: {}}`. _(see prop `modelValue`)_
       */
      this.$emit('update:modelValue', this.localSelected);
    },
  },
};
</script>

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

$color-grey: #5b737d;
$selected-Link: #007f8c;

@mixin transition($transition...) {
  -moz-transition: $transition;
  -o-transition: $transition;
  -webkit-transition: $transition;
  transition: $transition;
}

.mc-sidebar {
  position: absolute;
  top: 0;
  left: 0;
  z-index: var(--sidebar-z-index, 10);
  font-size: 14px;
  color: white;
  box-sizing: border-box;
  fill: white;
  width: 320px;
  background: #082435;
  display: block;
  height: 100vh;

  &__container {
    height: 100%;
    display: flex;
    flex-direction: column;

    &.has-bottom-panel {
      height: calc(100% - 88px);
    }
  }

  &__utilities {
    margin-bottom: 24px;

    &__item {
      margin: 4px 0px;

      &:first-child {
        margin-top: 0;
      }

      &:last-child {
        margin-bottom: 0;
      }
    }
  }

  &__trigger {
    cursor: pointer;
    background: none;
    border: none;
    padding: 0;
    min-height: 92px;
    width: 100%;
    font-size: inherit;
    font-family: inherit;
    position: relative;
    display: flex;
    outline: none;

    &__container {
      @include set-focus-floating-base();

      position: relative;
      margin: 28px 20px 28px 20px;
      height: 32px;
      width: 100%;

      & > * {
        position: absolute;
        top: 0px;
        right: 0px;
        width: 24px;
        height: 24px;
      }
    }

    &:focus-visible {
      & .mc-sidebar__trigger__container {
        @include set-focus-floating();
      }
    }
  }

  &.is-open {
    @include transition(width 300ms ease-in-out);
  }

  &.is-close {
    @include transition(width 300ms ease-in-out);

    width: 64px;
    padding: 0;
  }

  ul {
    list-style-type: none;
    margin: 0;
    padding: 0;
  }
}
</style>
