<template>
  <div>
    <component
      :is="setComponent"
      v-bind="setAttributes(featureGroup)"
      class="mc-feature-group"
      :class="{ 'is-selected': isSelected, 'is-open': open, 'is-close': !open }"
      @click="featureGroup.items?.length ? null : featureClick(featureGroup)"
    >
      <span class="mc-feature-group__container">
        <MTooltip
          v-if="!open && withTooltip"
          :id="featureGroup.code"
          :text="featureGroup.label"
          position="right"
        >
          <MIcon
            v-if="featureGroup.icon"
            :name="featureGroup.icon"
            class="mc-feature-group__icon"
            color="white"
            style="width: 24px; height: 24px"
          />
        </MTooltip>
        <MIcon
          v-else-if="featureGroup.icon"
          :name="featureGroup.icon"
          class="mc-feature-group__icon"
          style="width: 24px; height: 24px; fill: white"
        />
        <div v-if="open" style="display: flex">
          <span ref="label" class="mc-feature-group__label">
            {{ featureGroup.label }}
          </span>
          <div
            v-if="$refs.label?.offsetHeight < $refs.label?.scrollHeight"
            class="mc-feature-group__label__tooltip"
          >
            <div
              aria-hidden="true"
              class="mc-feature-group__label__tooltip__pointer"
            ></div>
            <span>{{ featureGroup.label }}</span>
          </div>
          <div v-if="featureGroup.items?.length">
            <MIcon
              v-if="!expand"
              name="ControlMore16"
              color="white"
              style="width: 16px; height: 16px"
            />
            <MIcon
              v-else
              name="ControlLess16"
              color="white"
              style="width: 16px; height: 16px"
            />
          </div>
        </div>
      </span>
    </component>
    <ul
      v-if="featureGroup.items"
      :id="`${featureGroup.code}-list`"
      ref="content"
      class="mc-feature-group__content"
      :class="{ 'is-open': open && expand, 'is-close': !open || !expand }"
    >
      <li
        v-for="(feature, i) in featureGroup.items"
        :key="i"
        @click.stop="featureClick(feature)"
      >
        <MSidebarFeature :feature="feature" :open="open" :selected="selected" />
      </li>
    </ul>
  </div>
</template>

<script>
import MIcon from '../icon/MIcon.vue';
import MSidebarFeature from './MSidebarFeature.vue';
import MTooltip from '../tooltip/MTooltip.vue';

export default {
  name: 'MSidebarFeatureGroup',
  components: { MTooltip, MSidebarFeature, MIcon },
  props: {
    /**
     * An object containing each of the elements relating to the display of a feature item.
     * @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] }}
     */
    featureGroup: {
      type: Object,
      default: () => ({}),
    },
    /**
     * Displays the list of "features" sub-items.
     */
    expand: {
      type: Boolean,
      default: false,
    },
    /**
     * Displays the labels of items in a tooltip when the sidebar is closed.
     */
    withTooltip: {
      type: Boolean,
      default: false,
    },
    /**
     * Determines the open or closed state of the sidebar
     */
    open: {
      type: Boolean,
      default: false,
    },
    /**
     * Same object as the one passed to the `modelValue` prop in the **MSidebar.vue** component.
     */
    selected: {
      type: Object,
      default: () => ({}),
    },
  },
  emits: ['feature-click', 'code-changed'],
  data() {
    return {
      isSelected: false,
    };
  },
  computed: {
    setComponent() {
      const data = this.featureGroup;
      const isLink = !!data.href;
      const routerLink =
        data.route && !this.featureGroup.items ? 'router-link' : null;
      const defaultComponent =
        isLink && !this.featureGroup.items ? 'a' : 'button';

      return routerLink ?? defaultComponent;
    },
  },
  watch: {
    selected: {
      handler: function () {
        this.updateSelected();
      },
      deep: true,
    },
    expand() {
      this.updateSelected();
      this.updateContentCSS();
    },
    open() {
      this.updateSelected();
      this.updateContentCSS();
    },
  },
  methods: {
    setAttributes(data) {
      const id = data.code;
      const href = data.href && !this.featureGroup.items ? data.href : null;
      const target = href && data.target ? data.target : null;
      const type = !data.href ? 'button' : null;
      const to = data.route && !this.featureGroup.items ? data.route : null;

      return {
        ...data.attrs,
        id,
        href,
        target,
        to,
        type,
        'aria-label': data.label,
        'aria-expanded': this.open && this.expand,
        'aria-controls': `${data.code}-list`,
      };
    },
    updateSelected() {
      this.isSelected =
        (this.selected?.lv0 &&
          this.featureGroup.code === this.selected?.lv0?.code &&
          (!this.selected.lv1 || !this.expand || !this.open)) ??
        false;
    },
    featureClick(feature) {
      if (!feature.disabled) {
        if (feature.items?.length) {
          this.$emit('feature-click', feature);
        } else {
          /**
           * Triggered each time an item that does not have sub-items is clicked.
           * - @arg {string} - the code value of the clicked item
           */
          this.$emit('code-changed', feature.code);
        }
      }
    },
    updateContentCSS() {
      if (this.$refs.content) {
        this.$refs.content.style.height = '';
        this.$refs.content.style.transition = 'none';
        const startHeight = window.getComputedStyle(this.$refs.content).height;

        this.$refs.content.classList.add(
          this.open && this.expand ? 'is-open' : 'is-close',
        );
        this.$refs.content.classList.remove(
          this.open && this.expand ? 'is-close' : 'is-open',
        );

        const height = window.getComputedStyle(this.$refs.content).height;
        this.$refs.content.style.height = startHeight;

        // wait until the next frame so that everything has time to update before starting the transition
        requestAnimationFrame(() => {
          this.$refs.content.style.transition = '';
          requestAnimationFrame(() => {
            this.$refs.content.style.height = height;
          });
        });

        // Clear the saved height values after the transition
        const handler = () => {
          this.$refs.content.style.height = '';
          this.$refs.content.removeEventListener('transitionend', handler);
        };

        this.$refs.content.addEventListener('transitionend', handler);
      }
    },
  },
};
</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-feature-group {
  background: none;
  border: none;
  color: white;
  cursor: pointer;
  display: inline-block;
  font-size: inherit;
  font-family: inherit;
  text-align: initial;
  margin: 0;
  padding: 0;
  min-height: 40px;
  overflow: hidden;
  text-decoration: none;
  outline: none;

  &__container {
    @include transition(margin 300ms ease-in-out);

    display: flex;
    align-items: center;
    margin: 5px 0;
    padding: 8px 0px;
  }

  &__label {
    @include set-font-scale('04', 'm');

    margin: 0 8px;
    width: 200px;
    min-width: 200px;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;

    &__tooltip {
      opacity: 0;
      transition: 0s opacity;
      background-color: #5b737d;
      border: 1px solid white;
      border-radius: 4px;
      position: absolute;
      pointer-events: none;
      left: calc(100% - 16px);
      padding: 8px 16px;
      width: 188px;

      &__pointer {
        position: absolute;
        top: 50%;
        left: -8px;
        top: calc(50% - 6px);
        width: 0;
        height: 0;
        border-top: 6px solid transparent;
        border-bottom: 6px solid transparent;
        border-right: 8px solid white;

        & div {
          position: relative;
          top: -6px;
          left: 2px;
          width: 0;
          height: 0;
          border-top: 6px solid transparent;
          border-bottom: 6px solid transparent;
          border-right: 8px solid #5b737d;
        }
      }
    }

    &:hover + .mc-feature-group__label__tooltip {
      opacity: 1;
      transition-delay: 1s;
    }
  }

  &__content {
    overflow: hidden;
    @include transition(height 300ms ease-in-out);

    &.is-close {
      height: 0;
    }

    &.is-open {
      height: auto;
    }
  }

  &:focus-visible,
  &:hover {
    background: #405d68;
  }

  &.is-selected {
    background: $selected-Link;
  }

  &.is-close {
    .mc-feature-group__container {
      margin: 0 20px;
      width: 24px;
    }
  }

  &.is-open {
    .mc-feature-group__container {
      margin: 0 32px;
    }
  }
}

ul,
li {
  list-style-type: none;
  margin: 0;
  padding: 0;
  display: flex;
  width: 100%;
}

ul {
  align-items: start;
  flex-direction: column;
  justify-content: center;

  li {
    flex-direction: column;
    box-sizing: border-box;
  }
}

:deep .mc-tooltip-container {
  cursor: pointer !important;
}
</style>
