<template>
  <div class="image-cell">
    <div
      v-for="(img, idx) in images"
      :key="idx"
      ref="containerRefs"
      :data-idx="idx"
      class="image-cell__thumb"
      @click="preview(img)"
    >
      <img
        v-if="loaded[idx]"
        :src="img.url"
        :alt="img.filename"
        class="image-cell__img"
      />
      <div v-else class="image-cell__placeholder">
        <FileImageOutlined />
      </div>
    </div>
    <span v-if="!images || images.length === 0" class="image-cell__empty">—</span>
  </div>
</template>

<script setup lang="ts">
import { ref, watch, onMounted, onUnmounted, nextTick } from 'vue'
import { FileImageOutlined } from '@ant-design/icons-vue'
import type { IAttachmentMeta } from '@/api/bitable'

const props = defineProps<{
  images: IAttachmentMeta[] | null | undefined
}>()

const containerRefs = ref<HTMLElement[]>([])
const loaded = ref<Record<number, boolean>>({})
let observer: IntersectionObserver | null = null

function setupObserver(): void {
  if (observer) {
    observer.disconnect()
  }
  observer = new IntersectionObserver(
    (entries) => {
      for (const entry of entries) {
        if (entry.isIntersecting) {
          const idx = Number((entry.target as HTMLElement).dataset.idx)
          loaded.value[idx] = true
          observer?.unobserve(entry.target)
        }
      }
    },
    { rootMargin: '100px' },
  )
  nextTick(() => {
    containerRefs.value.forEach((el) => {
      if (el && observer) observer.observe(el)
    })
  })
}

function preview(img: IAttachmentMeta): void {
  window.open(img.url, '_blank')
}

watch(
  () => props.images,
  () => {
    loaded.value = {}
    setupObserver()
  },
)

onMounted(() => {
  setupObserver()
})

onUnmounted(() => {
  observer?.disconnect()
})
</script>

<style scoped>
.image-cell {
  display: flex;
  flex-wrap: wrap;
  gap: var(--bitable-spacing-xs);
  padding: 2px 0;
}

.image-cell__thumb {
  width: 40px;
  height: 40px;
  border-radius: var(--bitable-radius-sm);
  overflow: hidden;
  cursor: pointer;
  background: var(--bitable-color-bg-secondary);
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--bitable-color-border);
}

.image-cell__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.image-cell__placeholder {
  color: var(--bitable-color-text-placeholder);
  font-size: var(--bitable-font-lg);
}

.image-cell__empty {
  color: var(--bitable-color-text-placeholder);
}
</style>
