<template>
  <view class="stacked-carousel">
    <view class="carousel-container" :style="containerStyle" @touchstart="handleTouchStart" @touchend="handleTouchEnd">
      <view v-for="(item, index) in displayList" :key="index" class="carousel-item"
        :class="{ 'active': index === activeIndex, 'no-transition': isResetting }" :style="getItemStyle(index)"
        @click="handleItemClick(index)" @transitionend="handleTransitionEnd">
        <slot :item="item" :index="index">
          <image :src="item.image" mode="aspectFill" />
        </slot>
      </view>
      <view v-if="showIndicator" class="carousel-indicators">
        <slot name="indicator" :current-index="getRealIndex(activeIndex)" :total="list.length"
          :handle-click="handleIndicatorClick">
          <view v-for="(_, index) in list" :key="index" :class="[
            indicatorStyle === 'dot' ? 'indicator-dot' : 'indicator-line',
            { 'active': getRealIndex(activeIndex) === index }
          ]" @click="handleIndicatorClick(index)" />
        </slot>
      </view>
    </view>
  </view>
</template>

<script>
/**
 * 3D堆叠轮播图组件
 * @description 一个支持3D堆叠效果的轮播图组件，具有自动播放、无缝循环、触摸滑动等功能
 */
export default {
  name: 'hbxw-stacked-carousel',
  props: {
    // 轮播图数据列表，每个元素必须包含image属性
    list: {
      type: Array,
      default: () => []
    },
    // 组件宽度，支持数字（单位rpx）或字符串
    width: {
      type: [String, Number],
      default: '750rpx'
    },
    // 组件高度，支持数字（单位rpx）或字符串
    height: {
      type: [String, Number],
      default: '400rpx'
    },
    // 是否自动播放
    autoplay: {
      type: Boolean,
      default: true
    },
    // 自动播放间隔时间（毫秒）
    interval: {
      type: Number,
      default: 3000
    },
    current: {
      type: Number,
      default: 0
    },
    // 是否启用无缝循环
    loop: {
      type: Boolean,
      default: false
    },
    // 是否显示指示器
    showIndicator: {
      type: Boolean,
      default: true
    },
    // 指示器样式，支持dot（圆点）和line（线条）
    indicatorStyle: {
      type: String,
      default: 'dot',
      validator: function (value) {
        return ['dot', 'line'].includes(value)
      }
    }
  },
  data() {
    return {
      activeIndex: 0, // 当前激活的轮播图索引
      timer: null, // 自动播放定时器
      touchStartX: 0, // 触摸开始位置
      touchEndX: 0, // 触摸结束位置
      displayList: [], // 实际显示的轮播图列表（包含首尾过渡图片）
      isResetting: false // 是否正在重置位置
    }
  },
  computed: {
    // 计算容器样式，处理宽高单位
    containerStyle() {
      return {
        width: typeof this.width === 'number' ? this.width + 'rpx' : this.width,
        height: typeof this.height === 'number' ? this.height + 'rpx' : this.height
      }
    }
  },
  mounted() {
    this.initDisplayList()
    this.startAutoplay()
  },
  beforeDestroy() {
    this.stopAutoplay()
  },
  methods: {
    // 初始化显示列表，处理无缝循环逻辑
    initDisplayList() {
      if (!this.list.length) return

      if (this.loop && this.list.length > 1) {
        // 在首尾添加额外的图片副本以实现无缝效果
        this.displayList = [
          this.list[this.list.length - 1],
          ...this.list,
          this.list[0]
        ]
        this.activeIndex = 1 // 从真实的第一张图片开始
      } else {
        this.displayList = [...this.list]
        this.activeIndex = 0
      }
    },
    // 计算每个轮播图项的样式，实现3D堆叠效果
    getItemStyle(index) {
      const diff = index - this.activeIndex
      const total = this.displayList.length
      let scale = 1
      let zIndex = 1
      let translateX = '0'

      if (diff === 0) {
        scale = 1
        zIndex = 3
      } else if (Math.abs(diff) === 1) {
        scale = 0.8
        zIndex = 2
        translateX = diff > 0 ? '60%' : '-60%'
      } else {
        scale = 0.6
        zIndex = 1
        translateX = diff > 0 ? '120%' : '-120%'
      }

      return {
        transform: `translateX(${translateX}) scale(${scale})`,
        zIndex: zIndex
      }
    },
    // 处理轮播图过渡结束事件，实现无缝循环
    handleTransitionEnd() {
      if (!this.loop || this.displayList.length <= 1) return

      // 处理无缝轮播的首尾过渡
      if (this.activeIndex === 0 || this.activeIndex === this.displayList.length - 1) {
        this.isResetting = true

        // 立即重置位置
        const targetIndex = this.activeIndex === 0 ? this.displayList.length - 2 : 1
        this.activeIndex = targetIndex

        // 在下一帧恢复过渡效果
        this.$nextTick(() => {
          setTimeout(() => {
            this.isResetting = false
          }, 50)
        })
      }
    },
    // 处理轮播图项点击事件
    handleItemClick(index) {
      this.$emit('click', this.getRealIndex(index), this.displayList[index])
      // if (index === this.activeIndex) return
      // const oldIndex = this.getRealIndex(this.activeIndex)
      // this.activeIndex = index
      // this.$emit('change', this.getRealIndex(index), oldIndex)
      // this.resetAutoplay()
    },
    // 处理轮播图切换，direction: 1向后，-1向前
    handleSlideChange(direction) {
      if (!this.displayList.length) return

      const oldIndex = this.getRealIndex(this.activeIndex)
      let newIndex

      if (this.loop && this.displayList.length > 1) {
        // 处理向前切换时的特殊情况
        if (direction === -1 && this.activeIndex === 1) {
          this.isResetting = true
          this.activeIndex = this.displayList.length - 2
          this.$nextTick(() => {
            setTimeout(() => {
              this.isResetting = false
            }, 50)
          })
        } else {
          newIndex = (this.activeIndex + direction + this.displayList.length) % this.displayList.length
          this.activeIndex = newIndex
        }
      } else {
        newIndex = (this.activeIndex + direction + this.list.length) % this.list.length
        this.activeIndex = newIndex
      }

      this.$emit('change', this.getRealIndex(this.activeIndex), oldIndex)
    },
    // 开始自动播放
    startAutoplay() {
      if (!this.autoplay) return
      this.timer = setInterval(() => {
        this.handleSlideChange(1)
      }, this.interval)
    },
    // 停止自动播放
    stopAutoplay() {
      if (this.timer) {
        clearInterval(this.timer)
        this.timer = null
      }
    },
    // 重置自动播放定时器
    resetAutoplay() {
      this.stopAutoplay()
      this.startAutoplay()
    },
    // 处理触摸开始事件
    handleTouchStart(e) {
      this.touchStartX = e.touches[0].clientX
      this.stopAutoplay()
    },
    // 处理触摸结束事件，判断滑动方向
    handleTouchEnd(e) {
      this.touchEndX = e.changedTouches[0].clientX
      const diff = this.touchEndX - this.touchStartX

      if (Math.abs(diff) > 50) { // 设置最小滑动距离阈值
        if (diff > 0) {
          // 向右滑，显示上一张
          this.handleSlideChange(-1)
        } else {
          // 向左滑，显示下一张
          this.handleSlideChange(1)
        }
      }

      this.startAutoplay()
    },

    // 获取真实的轮播图索引（考虑无缝循环的情况）
    getRealIndex(displayIndex) {
      if (this.loop && this.list.length > 1) {
        if (displayIndex === 0) return this.list.length - 1
        if (displayIndex === this.displayList.length - 1) return 0
        return displayIndex - 1
      }
      return displayIndex
    },

    // 处理指示器点击事件
    handleIndicatorClick(index) {
      const currentRealIndex = this.getRealIndex(this.activeIndex)
      if (currentRealIndex === index) return

      const targetDisplayIndex = this.loop ? index + 1 : index
      this.handleItemClick(targetDisplayIndex)
    }
  },
}
</script>

<style>
.stacked-carousel {
  position: relative;
  overflow: hidden;
}

.carousel-container {
  position: relative;
  margin: 0 auto;
}

.carousel-item {
  position: absolute;
  width: 100%;
  height: 100%;
  transition: all 0.5s ease;
  cursor: pointer;
}

.carousel-item.no-transition {
  transition: none;
}

.carousel-item image {
  width: 100%;
  height: 100%;
  border-radius: 20rpx;
}

.carousel-indicators {
  position: absolute;
  bottom: 20rpx;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 16rpx;
  z-index: 3;
}

.indicator-dot {
  width: 16rpx;
  height: 16rpx;
  border-radius: 50%;
  background-color: rgba(255, 255, 255, 0.5);
  transition: all 0.5s ease;
  cursor: pointer;
}

.indicator-dot.active {
  background-color: #ffffff;
  transform: scale(1.2);
}

.indicator-line {
  width: 24rpx;
  height: 8rpx;
  border-radius: 4rpx;
  background-color: rgba(255, 255, 255, 0.5);
  transition: all 0.5s ease;
  cursor: pointer;
}

.indicator-line.active {
  width: 32rpx;
  background-color: #ffffff;
}
</style>
