<template>
  <div
    class="fresh-home-video-list scroll-top scroll-bottom"
    :class="{ 'not-empty': videos.length > 0 }"
  >
    <div ref="content" class="fresh-home-video-list-content">
      <div v-if="videos.length === 0" class="fresh-home-video-list-empty">
        <VLoading v-if="loading" />
        <VEmpty v-else />
      </div>
      <VideoCardWrapper v-for="video of videos" v-else ref="cards" :key="video.id" :data="video" />
    </div>
  </div>
</template>
<script lang="ts">
import type { Ref, PropType } from 'vue'
import { defineComponent, ref } from 'vue'

import type { VideoCard } from '@/components/feeds/video-card'
import { enableHorizontalScroll } from '@/core/horizontal-scroll'
import { addComponentListener } from '@/core/settings'
import { VEmpty, VLoading } from '@/ui'

import { cleanUpScrollMask, setupScrollMask } from './scroll-mask'
import VideoCardWrapper from './VideoCardWrapper.vue'

export default defineComponent({
  components: {
    VEmpty,
    VLoading,
    VideoCardWrapper,
  },
  props: {
    videos: {
      type: Array as PropType<VideoCard[]>,
      default: () => [],
    },
    loading: {
      type: Boolean,
      default: true,
    },
  },
  setup: () => ({
    content: ref(null) as Ref<HTMLDivElement | null>,
    cards: ref(null) as Ref<InstanceType<typeof VideoCardWrapper>[] | null>,
  }),
  watch: {
    videos: {
      handler() {
        this.setupIntersection()
      },
      deep: true,
    },
    loaded(value) {
      if (value) {
        this.setupIntersection()
      }
    },
  },
  beforeUnmount() {
    cleanUpScrollMask(this.$el)
  },
  mounted() {
    const container = this.content as HTMLElement
    let cancel: () => void
    addComponentListener(
      'freshHome.horizontalWheelScroll',
      (scroll: boolean) => {
        if (scroll) {
          cancel = enableHorizontalScroll(container)
        } else {
          cancel?.()
        }
      },
      true,
    )
  },
  methods: {
    async setupIntersection() {
      await this.$nextTick()
      setupScrollMask({
        container: this.$el,
        items: this.cards.map(c => c.$el),
      })
    },
    offsetPage(offset: number) {
      const container = this.content as HTMLElement
      const style = getComputedStyle(container)
      const containerWidth = container.clientWidth
      const wrapperWidth =
        parseFloat(style.getPropertyValue('--card-width')) +
        parseFloat(style.getPropertyValue('--card-padding'))
      const pageWidth = Math.trunc(containerWidth / wrapperWidth) * wrapperWidth
      container.scrollBy(offset * pageWidth, 0)
    },
  },
})
</script>
<style lang="scss">
@import 'common';
@import 'effects';

.fresh-home-video-list {
  --card-height: var(--home-content-height);
  --card-width: 200px;
  --card-padding: 12px;
  position: relative;
  display: flex;
  flex: 1 0 0;
  width: 0;
  @include scroll-mask-x(36px, var(--home-base-color));

  &-content {
    @include h-center();
    @include no-scrollbar();
    overscroll-behavior: initial;
    flex: 1;
    min-height: calc(var(--home-content-height) + var(--card-padding) * 2);
  }
  &-empty {
    margin: var(--card-padding);
    border: 2px dashed #8884;
    border-radius: var(--home-card-radius);
    flex-grow: 1;
    align-self: stretch;
    @include h-center();
  }
  &.not-empty &-content {
    scroll-snap-type: x mandatory;
  }
}
</style>
