<template>
    <div class="slider-comp">
        <div class="slider-comp__tabs" ref="refTabs">
            <slot></slot>
        </div>
        <div class="slider-comp__controls">
            <div class="slider-comp__controls-container" :style="`--index: ${currentTabIndex}`">
                <div class="slider-comp__controls-circles">
                    <div
                        class="slider-comp__controls-circle"
                        v-for="(i, index) in tabs.length"
                        :key="index"
                        :class="{ 'slider-comp__controls-circle--active': index === currentTabIndex }"
                    ></div>
                    <div class="slider-comp__controls-pointer" v-show="tabs.length > 0"></div>
                </div>
            </div>
        </div>
        <FontAwesomeIcon
            class="slider-comp__controls-button slider-comp__controls-button--left"
            icon="chevron-left"
            @click="changeTabLeft()"
            v-show="buttonShowed.left"
        />
        <FontAwesomeIcon
            class="slider-comp__controls-button slider-comp__controls-button--right"
            icon="chevron-right"
            @click="changeTabRight()"
            v-show="buttonShowed.right"
        />
    </div>
</template>

<script setup lang="ts">
import { computed, onActivated, onBeforeUnmount, onMounted, ref, watch } from "vue";

const props = defineProps<{ type: "default" | "infinite"; automatic: boolean }>();
const emit = defineEmits(["index"]);

const refTabs = ref<Element | undefined>();
const tabs = ref<Element[]>([]);
const currentTabIndex = ref(0);
const nextTabIndex = ref(0);

const buttonShowed = ref({
    left: computed(() => props.type !== "infinite" && tabs.value.length > 1 && currentTabIndex.value > 0),
    right: computed(() => props.type !== "infinite" && tabs.value.length > 1 && currentTabIndex.value < tabs.value.length - 1),
});

function changeTabLeft() {
    if (currentTabIndex.value > 0) {
        changeTab(currentTabIndex.value - 1);
    } else if (props.type === "infinite") {
        changeTab(tabs.value.length - 1);
    }
}
function changeTabRight() {
    if (currentTabIndex.value < tabs.value.length - 1) {
        changeTab(currentTabIndex.value + 1);
    } else if (props.type === "infinite") {
        changeTab(0);
    }
}
function changeTab(index: number) {
    let left = (tabs.value[index] as HTMLElement).offsetLeft;

    refTabs.value?.scroll({ left, behavior: "smooth" });

    //tabs.value[index].scrollIntoView({ behavior: "smooth", block: "nearest", inline: "nearest" });
    nextTabIndex.value = index;
    emit("index", index);
}

function callback(entries: IntersectionObserverEntry[]) {
    const trueEntry = entries.find((x) => x.isIntersecting);

    if (trueEntry) {
        const index = tabs.value.indexOf(trueEntry.target);

        const tabChangedProgramatically = nextTabIndex.value !== currentTabIndex.value;

        if (!tabChangedProgramatically) {
            changeTab(index);
        }

        currentTabIndex.value = index;
    }
}
const observer = new IntersectionObserver(callback, { rootMargin: "0% -40%" });

onMounted(() => {
    createTabsList();
});

onActivated(() => {
    if (props.automatic) automaticTabChange();
});

function createTabsList() {
    if (!refTabs.value) return;

    for (const tab of refTabs.value.children) {
        if (tab.classList.contains("slider-tab-comp")) {
            tabs.value.push(tab);
            observer.observe(tab);
        }
    }
}
onBeforeUnmount(() => {
    observer.disconnect();
});

let automaticTimeout = 0;

function automaticTabChange() {
    clearTimeout(automaticTimeout);

    automaticTimeout = setTimeout(() => {
        changeTabRight();
    }, 5000);
}
watch(
    () => currentTabIndex.value,
    () => {
        if (props.automatic) {
            automaticTabChange();
        }
    }
);
</script>

<style lang="scss">
.slider-comp {
    position: relative;
    display: flex;
    flex-direction: column;
    height: 100%;

    &__tabs {
        display: flex;
        height: 100%;
        overflow-x: scroll;
        scroll-snap-type: x mandatory;
        scroll-snap-stop: always;

        -ms-overflow-style: none;
        scrollbar-width: none;

        &::-webkit-scrollbar {
            display: none;
        }
    }

    &__controls {
        display: flex;
        justify-content: center;
        padding: r(10) 0 r(20) 0;
        user-select: none;
    }

    &__controls-container {
        position: relative;
        display: flex;
        align-items: center;
        gap: r(15);
    }

    &__controls-circles {
        position: relative;
        display: flex;
        gap: r(15);
    }

    &__controls-circle {
        width: r(15);
        height: r(15);
        border-radius: 50%;
        border: r(2) solid color("ui-background");
        transition: box-shadow 0.28s ease;

        &--active {
            box-shadow: 0 0 r(5) color("ui-background");
        }
    }

    &__controls-button {
        position: absolute;
        top: calc(50% - r(45));
        display: flex;
        justify-content: center;
        align-items: center;
        width: 10%;
        height: r(40);
        color: color("ui-background");
        cursor: pointer;

        &--left {
            left: 0;
        }

        &--right {
            right: 0;
        }
    }

    &__controls-pointer {
        position: absolute;
        top: r(3);
        left: calc(r(3) + (var(--index)) * r(30));

        width: r(9);
        height: r(9);
        border-radius: 50%;

        background: color("ui-background");

        transition: left 0.28s ease;
    }
}
</style>
