<template>
  <!-- 参考 https://blog.csdn.net/weixin_44198965/article/details/147831036 -->
  <div class="waterfall-container">
    <!-- 列容器 -->
    <div ref="columnWrapper" class="waterfall-column-wrapper">
      <!-- 瀑布流项 -->
      <div
        v-for="(item, index) in renderedList"
        :key="item.id || index"
        v-lazy-load="item.image || item.cover"
        class="waterfall-item"
      >
        <!-- 图片类型 -->
        <div v-if="item.type === 'image'" class="item-content" @click="jump(item.linkUrl)">
          <img
            :src="placeholder"
            :alt="item.title || '图片'"
            class="item-image"
          >
          <div v-if="item.title" class="item-title">{{ item.title }}</div>
        </div>

        <!-- 视频类型 -->
        <div v-else-if="item.type === 'video'" class="item-content">
          <video
            :poster="placeholder"
            controls
            class="item-video"
          >
            <source :src="item.videoUrl" type="video/mp4">
          </video>
          <div v-if="item.title" class="item-title">{{ item.title }}</div>
        </div>

        <!-- 图文类型 -->
        <div v-else class="item-content">
          <img
            v-if="item.image"
            :src="placeholder"
            :alt="item.title || '图文'"
            class="item-image"
          >
          <div v-if="item.title" class="item-title">{{ item.title }}</div>
          <div v-if="item.desc" class="item-desc">{{ item.desc }}</div>
        </div>
      </div>
    </div>

    <!-- 加载状态 -->
    <div v-if="loading" class="loading-more">
      加载中...
    </div>
    <div v-if="isComplete && renderedList.length > 0" class="load-complete">
      没有更多内容了
    </div>
  </div>
</template>

<script>
export default {
  name: 'Waterfall',

  directives: {
    lazyLoad: {
      inserted(el, binding, vnode) {
        const observer = new IntersectionObserver((entries) => {
          entries.forEach(entry => {
            if (entry.isIntersecting) {
              const img = el.tagName === 'IMG' ? el : el.querySelector('img')
              if (img) {
                img.src = binding.value
                // 图片加载完成后重新布局
                img.onload = () => {
                  vnode.context.layoutItems()
                }
                // 图片加载错误处理
                img.onerror = () => {
                  if (vnode.context.placeholder) {
                    img.src = vnode.context.placeholder
                  }
                }
              }
              observer.unobserve(el)
            }
          })
        }, {
          rootMargin: '0px 0px 100px 0px' // 提前100px加载
        })

        observer.observe(el)

        el._observer = observer
      },
      unbind(el) {
        if (el._observer) {
          el._observer.disconnect()
        }
      }
    }
  },

  // 定义组件props
  props: {
    // 数据源数组
    list: {
      type: Array,
      required: true,
      default: () => []
    },
    // 列数配置
    columns: {
      type: Number,
      default: 2,
      validator: function(value) {
        return value >= 1 && value <= 5 // 限制列数在1-5之间
      }
    },
    // 列间距
    gap: {
      type: Number,
      default: 10
    },
    // 是否开启懒加载
    lazyLoad: {
      type: Boolean,
      default: true
    },
    // 触底加载的阈值（距离底部多少像素触发加载）
    loadThreshold: {
      type: Number,
      default: 100
    },
    // 图片加载时的占位图
    placeholder: {
      type: String,
      default: '改成你的图片'
    },
    totalItems: {
      type: Number,
      default: 0
    }
  },

  data() {
    return {
      waterfallRef: null, // 瀑布流容器引用
      columnHeights: [], // 每列当前高度数组
      columnWrapperRef: null, // 列容器引用
      loading: false, // 加载状态
      isComplete: false, // 是否已加载全部数据
      renderedList: [], // 已渲染的数据列表
      pageSize: 20, // 每次加载的数据量
      currentPage: 1 // 当前页码
    }
  },

  computed: {
    // 计算列宽度（根据容器宽度和列数计算）
    columnWidth() {
      if (!this.waterfallRef) return 0
      const containerWidth = this.waterfallRef.clientWidth
      return (containerWidth - (this.columns - 1) * this.gap) / this.columns
    }
  },

  watch: {
    // 监听列数变化
    columns(newVal, oldVal) {
      if (newVal !== oldVal) {
        this.resetLayout()
      }
    },

    // 监听数据源变化
    list: {
      handler(newList) {
        this.renderedList = newList // 直接同步父组件数据（无需分页切片）
        this.$nextTick(() => this.layoutItems())
      },
      deep: true
    }
  },

  mounted() {
    this.scrollContainer = this.$el
    this.waterfallRef = this.$el
    this.columnWrapperRef = this.$el.querySelector('.waterfall-column-wrapper')

    this.resetLayout()
    if (this.lazyLoad) {
      this.scrollContainer.addEventListener('scroll', this.handleScroll)
    }
    window.addEventListener('resize', this.handleResize)
  },

  beforeDestroy() {
    if (this.lazyLoad && this.scrollContainer) {
      this.scrollContainer.removeEventListener('scroll', this.handleScroll)
    }
    window.removeEventListener('resize', this.handleResize)
  },

  methods: {
    // 初始化列高度数组
    initColumnHeights() {
      this.columnHeights = new Array(this.columns).fill(0)
    },

    // 初始化渲染数据
    initRenderList() {
      this.renderedList = this.list.slice(0, this.pageSize)
      this.currentPage = 1
      this.isComplete = this.renderedList.length >= this.list.length
    },

    // 重置瀑布流布局
    resetLayout() {
      this.initColumnHeights()
      this.initRenderList()
      this.$nextTick(() => {
        this.layoutItems()
      })
    },

    // 瀑布流布局算法
    layoutItems() {
      if (!this.columnWrapperRef || !this.waterfallRef) return

      // 获取所有子元素
      const items = this.columnWrapperRef.children
      if (!items || items.length === 0) return

      // 初始化列高度
      this.initColumnHeights()

      // 临时列高度副本用于计算
      const tempColumnHeights = [...this.columnHeights]

      // 遍历所有子元素进行布局
      Array.from(items).forEach((item, index) => {
        // 找到当前最短的列
        const minHeight = Math.min(...tempColumnHeights)
        const columnIndex = tempColumnHeights.indexOf(minHeight)

        // 计算位置
        const left = columnIndex * (this.columnWidth + this.gap)
        const top = minHeight

        // 应用样式
        item.style.position = 'absolute'
        item.style.width = `${this.columnWidth}px`
        item.style.left = `${left}px`
        item.style.top = `${top}px`
        item.style.transition = 'all 0.3s ease'

        // 更新列高度
        tempColumnHeights[columnIndex] += item.clientHeight + this.gap
      })

      // 更新列高度
      this.columnHeights = tempColumnHeights

      // 设置容器高度
      const maxHeight = Math.max(...tempColumnHeights)
      this.columnWrapperRef.style.height = `${maxHeight}px`
    },

    // 滚动事件处理
    // handleScroll() {
    //   if (this.loading || this.isComplete) return

    //   const scrollTop = document.documentElement.scrollTop || document.body.scrollTop
    //   const windowHeight = window.innerHeight
    //   const scrollHeight = document.documentElement.scrollHeight

    //   // 判断是否触底
    //   if (scrollTop + windowHeight >= scrollHeight - this.loadThreshold) {
    //     this.loadMore()
    //   }
    // },

    handleScroll() {
      if (this.loading || (this.totalItems > 0 && this.renderedList.length >= this.totalItems)) {
        return
      }

      // 获取滚动容器（父组件的.content-main）
      const scrollContainer = this.$parent.$el.querySelector('.content-main') || window
      let scrollTop, clientHeight, scrollHeight

      if (scrollContainer === window) {
        scrollTop = document.documentElement.scrollTop || document.body.scrollTop
        clientHeight = window.innerHeight
        scrollHeight = document.documentElement.scrollHeight
      } else {
        // 关键：用滚动容器的实际尺寸计算（避免父组件padding影响）
        scrollTop = scrollContainer.scrollTop
        clientHeight = scrollContainer.clientHeight
        scrollHeight = scrollContainer.scrollHeight
      }

      // 触底阈值：距离底部100px时触发加载（可调整）
      if (scrollTop + clientHeight >= scrollHeight - this.loadThreshold) {
        this.$emit('scroll-end') // 触发父组件的loadMoreData
        console.log('触发加载更多')
      }
    },

    // 加载更多数据
    loadMore() {
      if (this.loading || this.isComplete) return

      this.loading = true

      // 模拟异步加载
      setTimeout(() => {
        try {
          const nextPage = this.currentPage + 1
          const startIndex = (nextPage - 1) * this.pageSize
          const endIndex = nextPage * this.pageSize

          if (startIndex >= this.list.length) {
            this.isComplete = true
            return
          }

          const newItems = this.list.slice(startIndex, endIndex)
          this.renderedList = [...this.renderedList, ...newItems]
          this.currentPage = nextPage

          // 检查是否已加载全部数据
          if (endIndex >= this.list.length) {
            this.isComplete = true
          }

          // 等待DOM更新后重新布局
          this.$nextTick(() => {
            this.layoutItems()
          })
        } catch (error) {
          console.error('加载更多数据失败:', error)
        } finally {
          this.loading = false
        }
      }, 500)
    },
    jump(url) {
      window.location.href = url
    },
    // 响应式处理窗口大小变化
    handleResize() {
      this.resetLayout()
    }
  }
}
</script>

<style scoped>
.waterfall-container {
  position: relative;
  width: calc(100%);
  height: 800px;
  overflow: hidden;
  overflow-y: auto;
}

.waterfall-column-wrapper {
  position: relative;
  width: 100%;

}

.waterfall-item {
  margin-bottom: 10px;
  break-inside: avoid;
  box-sizing: border-box;
  background: #fff;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  transition: all 0.3s ease;
}

.waterfall-item:hover {
  transform: translateY(-5px);
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}

.item-content {
  padding: 12px;
}

.item-image, .item-video {
  width: 100%;
  border-radius: 4px;
  display: block;
  background: #f5f5f5;
}

.item-video {
  aspect-ratio: 9/16;
  object-fit: cover;
}

.item-title {
  margin-top: 8px;
  font-size: 24px;
  line-height: 1.4;
  color: #333;
  font-weight: bold;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.item-desc {
  margin-top: 6px;
  font-size: 12px;
  color: #666;
  line-height: 1.4;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.loading-more, .load-complete {
  text-align: center;
  padding: 20px 0;
  color: #999;
  font-size: 14px;
}
</style>
