<script lang="ts" setup>
import { onUnmounted } from 'vue';
import { ref } from 'vue';
import { onMounted } from 'vue';

type Menu = {
  element?: HTMLElement;
  anchor: string;
  name: string;
  sub?: boolean;
  tab?: string;
  useBtn?: boolean;
};

const props = defineProps<{
  menu: Menu[];

  scrollElement?: Element | HTMLElement | string;

  foreground?: string;
  background?: string;

  active?: {
    foreground?: string;
    background?: string;
  };
}>();

const currentScrollElement = ref<Element | HTMLElement>();

function handleClick(menu: Menu) {
  const element = document.getElementById(menu.anchor);

  if (element) {
    element.scrollIntoView({
      behavior: 'smooth',
      block: 'start',
    });
  }
}

const activeMenu = ref(props.menu.at(0)?.anchor || '');

function onScroll() {
  let current = activeMenu.value;

  if (!currentScrollElement.value) return;

  const container = currentScrollElement.value;

  props.menu.forEach((v) => {
    if (!v.element) v.element = document.getElementById(v.anchor) || undefined;
    if (!v.element) return;

    const containerRect = container.getBoundingClientRect();
    const elementRect = v.element.getBoundingClientRect();

    if (containerRect.y + containerRect.height / 5 >= elementRect.y) {
      current = v.anchor;
    }
  });
  activeMenu.value = current;
}

onMounted(() => {
  if (typeof props.scrollElement === 'string' || !props.scrollElement) {
    const element = document.querySelector(props.scrollElement || 'body');
    if (element) currentScrollElement.value = element;
  } else {
    currentScrollElement.value = props.scrollElement;
  }

  currentScrollElement.value?.addEventListener('scroll', onScroll);
});
onUnmounted(() => {
  currentScrollElement.value?.removeEventListener('scroll', onScroll);
});
</script>

<template>
  <div class="side-menu__container">
    <template v-for="v in menu" :key="v.anchor">
      <span
        :style="{
          '--side-menu__fg': activeMenu !== v.anchor ? foreground : undefined,
          '--side-menu__bg': activeMenu !== v.anchor ? background : undefined,
          '--side-menu__fg-active': active?.foreground,
          '--side-menu__bg-active': active?.background,
        }"
        class="side-menu__item row items-center justify-between no-wrap"
        :class="{
          'side-menu__active': activeMenu === v.anchor,
          'side-menu__sub': v.sub || false,
        }"
        @click="handleClick(v)"
      >
        <span
          class="row no-wrap items-center"
          :class="{ 'app-text-muted': v.sub && activeMenu !== v.anchor }"
        >
          <div v-if="v.sub" class="circle-2"></div>
          <div
            v-if="v.sub"
            class="surface-tab circle flex justify-center q-mx-md"
          >
            {{ menu.filter((v) => v.sub === true).indexOf(v) + 1 }}
          </div>
          {{ v.name }}
        </span>
        <slot v-if="v.useBtn" :name="`btn-${v.anchor}`"></slot>
      </span>
    </template>
  </div>
</template>

<style scoped>
.side-menu__container {
  display: flex;
  flex-direction: column;
  gap: var(--size-1);
  max-width: 100%;

  & > .side-menu__item {
    transition: 0.3s background ease-in-out;
    color: var(--side-menu__fg, inherit);
    background: var(--side-menu__bg, inherit);
    padding: var(--size-2) var(--size-4);
    border-radius: var(--radius-2);
    cursor: pointer;

    &.side-menu__sub {
      /* margin-left: 1rem; */
    }

    &.side-menu__active {
      --side-menu__fg: var(--side-menu__fg-active, inherit);
      --side-menu__bg: var(--side-menu__bg-active, inherit);
      font-weight: 600;
    }
  }
}

.circle {
  width: 15px;
  height: 15px;
  font-size: 12px;
  border-radius: 50%;
}

.circle-2 {
  background: var(--surface-tab);
  width: 7px;
  height: 7px;
  border-radius: 50%;
}
</style>
