<script setup lang="ts">
import { onMounted, onUnmounted, reactive, ref, watch } from 'vue'
import {
  getSlideOffset,
  slideInit,
  slideReset,
  slideTouchEnd,
  slideTouchMove,
  slideTouchStart,
} from '@/utils/slide'
import { SlideType } from '@/utils/const_var'
import { _css } from '@/utils/dom'

const props = defineProps({
  index: { type: Number, default: 0 },
  name: { type: String, default: '' },
  autoplay: { type: Boolean, default: false },
  indicator: { type: Boolean, default: false },
  changeActiveIndexUseAnim: { type: Boolean, default: true },
})

const emit = defineEmits<{ 'update:index': [number] }>()

let ob: MutationObserver | null = null
const slideListEl = ref<HTMLElement | null>(null)

const state = reactive({
  judgeValue: 20,
  type: SlideType.HORIZONTAL,
  name: props.name,
  localIndex: props.index,
  needCheck: true,
  next: false,
  isDown: false,
  start: { x: 0, y: 0, time: 0 },
  move: { x: 0, y: 0 },
  wrapper: { width: 0, height: 0, childrenLength: 0 },
})

watch(
  () => props.index,
  (newVal) => {
    if (state.localIndex !== newVal) {
      state.localIndex = newVal
      if (!slideListEl.value) return
      if (props.changeActiveIndexUseAnim) {
        _css(slideListEl.value, 'transition-duration', '300ms')
      }
      _css(
        slideListEl.value,
        'transform',
        `translate3d(${getSlideOffset(state, slideListEl.value)}px, 0, 0)`,
      )
    }
  },
)

onMounted(() => {
  if (!slideListEl.value) return
  slideInit(slideListEl.value, state)
  if (props.autoplay) {
    setInterval(() => {
      if (state.localIndex === state.wrapper.childrenLength - 1) {
        emit('update:index', 0)
      } else {
        emit('update:index', state.localIndex + 1)
      }
    }, 3000)
  }
  ob = new MutationObserver(() => {
    if (slideListEl.value) state.wrapper.childrenLength = slideListEl.value.children.length
  })
  ob.observe(slideListEl.value, { childList: true })
})

onUnmounted(() => {
  ob?.disconnect()
})

function touchStart(e: PointerEvent) {
  if (slideListEl.value) slideTouchStart(e, slideListEl.value, state)
}

function touchMove(e: PointerEvent) {
  if (slideListEl.value) slideTouchMove(e, slideListEl.value, state)
}

function touchEnd(e: PointerEvent) {
  slideTouchEnd(e, state)
  if (slideListEl.value) slideReset(e, slideListEl.value, state, emit)
}
</script>

<template>
  <div class="slide horizontal">
    <div
      v-if="indicator && state.wrapper.childrenLength"
      class="indicator-bullets"
    >
      <div
        v-for="item in state.wrapper.childrenLength"
        :key="item"
        class="bullet"
        :class="{ active: state.localIndex === item - 1 }"
      />
    </div>
    <div
      ref="slideListEl"
      class="slide-list"
      @pointerdown.prevent="touchStart"
      @pointermove.prevent="touchMove"
      @pointerup.prevent="touchEnd"
    >
      <slot />
    </div>
  </div>
</template>

<style scoped lang="less">
.indicator-bullets {
  position: absolute;
  bottom: 10rem;
  z-index: 2;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  justify-content: center;
  gap: 7rem;

  .bullet {
    width: 5rem;
    height: 5rem;
    border-radius: 50%;
    background: var(--second-btn-color);

    &.active {
      background: white;
    }
  }
}
</style>
