<template>
  <div
    :class="ui.wrapper"
    v-bind="attrs"
  >
    <div
      ref="carouselRef"
      :class="ui.container"
      class="no-scrollbar"
    >
      <div
        v-for="(item, index) in items"
        :key="index"
        :class="ui.item"
        :role="indicators ? 'tabpanel' : null"
      >
        <slot
          :item="item"
          :index="index"
        />
      </div>
    </div>

    <div
      v-if="arrows"
      :class="ui.arrows.wrapper"
    >
      <slot
        name="prev"
        :on-click="onClickPrev"
        :disabled="isFirst"
      />

      <slot
        name="next"
        :on-click="onClickNext"
        :disabled="isLast"
      />
    </div>

    <div
      v-if="indicators"
      role="tablist"
      :class="ui.indicators.wrapper"
    >
      <template
        v-for="page in pages"
        :key="page"
      >
        <slot
          name="indicator"
          :on-click="onClick"
          :active="page === currentPage"
          :page="page"
        >
          <button
            type="button"
            role="tab"
            :aria-selected="page === currentPage"
            :class="[
              ui.indicators.base,
              page === currentPage ? ui.indicators.active : ui.indicators.inactive
            ]"
            :aria-label="`set slide ${page}`"
            @click="onClick(page)"
          />
        </slot>
      </template>
    </div>
  </div>
</template>

<script setup lang="ts" generic="T">
import {useScroll, useResizeObserver, useElementSize} from '@vueuse/core'
import {useCarouselScroll} from "#adata-ui/composables/useCarouselScroll";
import {ui as defaultUi} from './config.ui';
import {computed, ref, toRefs} from "vue";
import type {Ui} from "#adata-ui/components/elements/carousel/types";
import {mergeConfig} from "#adata-ui/components/utils";

defineOptions({
  inheritAttrs: false
})
const attrs = useAttrs()


interface Props {
  items: T[]
  indicators?: boolean
  arrows?: boolean
  defaultUi?: Ui
}

const props = withDefaults(defineProps<Props>(), {
  indicators: false,
  arrows: false,
  defaultUi: () => {
  }
})
const ui = computed(() =>mergeConfig<Ui>(defaultUi, props.defaultUi))
const carouselRef = ref<HTMLElement>()
const itemWidth = ref(0)

const {x, arrivedState} = useScroll(carouselRef, {behavior: 'smooth'})
const {width: carouselWidth} = useElementSize(carouselRef)

const {left: isFirst, right: isLast} = toRefs(arrivedState)

useCarouselScroll(carouselRef)

useResizeObserver(carouselRef, (entries) => {
  const [entry] = entries

  itemWidth.value = entry?.target?.firstElementChild?.clientWidth || 0
})

const currentPage = computed(() => Math.round(x.value / itemWidth.value) + 1)

const pages = computed(() => {
  if (!itemWidth.value) {
    return 0
  }

  return props.items.length - Math.round(carouselWidth.value / itemWidth.value) + 1
})

function onClickNext() {
  x.value += itemWidth.value
}

function onClickPrev() {
  x.value -= itemWidth.value
}

function onClick(page: number) {
  x.value = (page - 1) * itemWidth.value
}

defineExpose({
  pages,
  page: currentPage,
  prev: onClickPrev,
  next: onClickNext,
  select: onClick
})
</script>

<style scoped>
/* Hide scrollbar for Chrome, Safari and Opera */
.no-scrollbar::-webkit-scrollbar {
  display: none;
}

/* Hide scrollbar for IE, Edge and Firefox */
.no-scrollbar {
  -ms-overflow-style: none; /* IE and Edge */
  scrollbar-width: none; /* Firefox */
}
</style>
