<template>
  <div
    ref="container"
    class="mc-tooltip-container"
    :class="classObject"
    :aria-describedby="id"
    @mouseover="visible = true"
    @mouseleave="visible = false"
  >
    <!-- @slot Use this slot to insert the HTML content on which the Tooltip should be positioned -->
    <slot />

    <Teleport :to="appendTo">
      <Transition @after-enter="onAfterEnter" @leave="onLeave">
        <div
          v-if="visible && getEmptyState"
          :id="id"
          ref="tooltip"
          class="mc-tooltip"
          :class="classObjectTooltip"
          :style="styleObjectListbox"
          role="tooltip"
        >
          <span class="mc-tooltip__label">
            {{ label || text }}
          </span>
          <span v-if="!nopointer" class="mc-tooltip__arrow">&nbsp;</span>
        </div>
      </Transition>
    </Teleport>
  </div>
</template>

<script>
import { useElementBounding } from '@vueuse/core';

/**
 * > A tooltip allows you to display further information to the user when needed. It can also be used to explicitely specify a visual element like an icon.
 *
 * The `MTooltip` component is the **Vue.js** implementation of the **Tooltip** component of Mozaic Design System.<br/>
 * The full specification of this component is available in [the associated documentation](https://mozaic.adeo.cloud/components/tooltip/).
 */
export default {
  name: 'MTooltip',
  props: {
    /**
     * The Tooltip id _(required)_
     */
    id: {
      type: String,
      required: true,
    },
    /**
     * The Tooltip label
     */
    label: {
      type: String,
      default: '',
    },
    /**
     * The Tooltip text
     * @deprecated
     * @ignore
     */
    text: {
      type: String,
      default: '',
    },
    /**
     * Allows to define the position of the Tooltip
     * @values top, right, bottom, left
     */
    position: {
      type: String,
      default: 'top',
      validator: (value) => ['top', 'right', 'bottom', 'left'].includes(value),
    },
    /**
     * Allows to display or not the pointer of the Tooltip
     */
    nopointer: {
      type: Boolean,
      default: false,
    },
    /**
     * A query selector that defines the target element to which to append the content of the Teleport
     */
    appendTo: {
      type: String,
      default: 'body',
    },
  },
  data() {
    return {
      visible: false,
      isVisible: false,
      tooltipTop: undefined,
      tooltipRight: undefined,
      tooltipBottom: undefined,
      tooltipLeft: undefined,
    };
  },
  computed: {
    classObject() {
      return {
        'is-empty': !this.getEmptyState,
      };
    },
    classObjectTooltip() {
      return {
        [`mc-tooltip--${this.position}`]: this.position,
        'is-visible': this.isVisible,
      };
    },
    styleObjectListbox() {
      return {
        top: this.tooltipTop,
        right: this.tooltipRight,
        bottom: this.tooltipBottom,
        left: this.tooltipLeft,
      };
    },
    getEmptyState() {
      return !!this.label?.length || !!this.text?.length;
    },
  },
  methods: {
    setTooltipPosition() {
      let topValue = undefined;
      let leftValue = undefined;
      let rightValue = undefined;

      // container
      const containerEl = useElementBounding(this.$refs.container);
      const containerTop = Math.floor(containerEl.top.value);
      const containerHeight = Math.floor(containerEl.height.value);
      const containerLeft = Math.floor(containerEl.left.value);
      const containerWidth = Math.floor(containerEl.width.value);

      // Calculate position
      const top50 = containerTop + window.scrollY + containerHeight / 2; // top: 50%;
      const left50 = containerLeft + containerWidth / 2; // left: 50%;

      switch (this.position) {
        case 'right':
          topValue = top50; // top: 50%;
          // rightValue = containerLeft; // right: 0;
          leftValue = containerLeft + containerWidth; // right: 0;
          break;
        case 'bottom':
          topValue = containerTop + window.scrollY + containerHeight; // bottom: 0;
          leftValue = left50; // left: 50%;
          break;
        case 'left':
          topValue = top50; // top: 50%;
          leftValue = containerLeft; // left: 0;
          break;
        default:
          topValue = containerTop + window.scrollY; // top: 0;
          leftValue = left50; // left: 50%;
      }

      this.tooltipTop = topValue && `${topValue}px`;
      this.tooltipLeft = leftValue && `${leftValue}px`;
      this.tooltipRight = rightValue && `${rightValue}px`;

      this.isVisible = true;
    },
    onAfterEnter() {
      this.setTooltipPosition();
    },
    onLeave() {
      this.isVisible = false;
    },
  },
};
</script>

<style scoped lang="scss">
@import 'settings-tools/all-settings';
// @import 'components/c.tooltip';
/* mqp:start */
.mc-tooltip-container {
  display: inline-flex;
  position: relative;

  &:not(.is-empty) {
    &:focus,
    &:hover {
      cursor: help;
    }
  }
}

.mc-tooltip {
  $parent: get-parent-selector(&);

  box-sizing: border-box;
  min-width: magic-unit-rem(6.625, true);
  max-width: magic-unit-rem(13.75, true);
  position: absolute;
  visibility: hidden;
  opacity: 0;
  z-index: 1999999999;
  transition: all 0.3s ease-out;

  @supports (width: max-content) {
    width: max-content;
  }

  &__arrow {
    font-size: 0;
    line-height: 0;
    position: absolute;
    z-index: 2;

    &::before {
      background: transparent
        url(inline-icons('tooltip-arrow', $color-tooltip-border)) no-repeat;
      background-size: px-to-rem(10);
      content: '';
      display: block;
      height: px-to-rem(10);
      width: px-to-rem(10);
    }

    &::after {
      background: transparent
        url(inline-icons('tooltip-arrow', $color-tooltip-background)) no-repeat;
      background-size: $mu050;
      content: '';
      height: $mu050;
      position: absolute;
      width: $mu050;
      left: 2px;
      top: 1px;
    }
  }

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

    background-color: $color-tooltip-background;
    border: get-border('s') solid $color-tooltip-border;
    border-radius: get-border-radius('m');
    color: $color-font-lightest;
    display: inline-block;
    padding: magic-unit-rem(0.4375, true) $mu100;
    position: relative;
    text-align: center;
    white-space: normal;
    z-index: 1;
  }

  &.is-visible {
    opacity: 1;
    visibility: visible;
  }

  &--top {
    transform: translate(-50%, calc(-100% - #{$mu075}));

    #{$parent}__arrow {
      bottom: 0;
      left: 50%;
      transform: translate(-50%, 90%) rotate(-90deg);
    }
  }

  &--right {
    transform: translate(#{$mu075}, -50%);

    #{$parent}__arrow {
      top: 50%;
      left: 0;
      transform: translate(-90%, -50%);
    }
  }

  &--bottom {
    transform: translate(-50%, #{$mu075});

    #{$parent}__arrow {
      top: 0;
      left: 50%;
      transform: translate(-50%, -90%) rotate(90deg);
    }
  }

  &--left {
    transform: translate(calc(-100% - #{$mu075}), -50%);

    #{$parent}__arrow {
      top: 50%;
      right: 0;
      transform: translate(90%, -50%) rotate(180deg);
    }
  }

  &--no-pointer {
    #{$parent}__arrow {
      display: none;
    }
  }
}
/* mqp:end */
</style>
