<template>
    <view class="u-waterfall">
        <!-- 新增支持多列布局 -->
        <view 
            v-for="(column, index) in columnList" 
            :key="index"
            :ref="`u-column-${index}`"
            :id="`u-column-${index}`"
            class="u-column"
        >
            <slot name="column"
                :colIndex="index" 
                :colList="column">
            </slot>
            <slot name="left"
                :colIndex="index" 
                :leftList="column">
            </slot>
            <template v-if="!$slots['left'] && !$slots['column']" v-for="(item, itemIndex) in column" :key="itemIndex">
                <slot :item="item" :itemIndex="itemIndex"></slot>
            </template>
        </view>
    </view>
</template>

<script>
    /**
     * waterfall 瀴布流
     * @description 这是一个瀑布流形式的组件，对原组件进行升级已经支持自定义列数模式，便于适配不同屏幕。搭配loadMore 加载更多组件，让您开箱即用，眼前一亮。
     * @tutorial https://uview-plus.jiangruyi.com/components/waterfall.html
     * @property {Array} flow-list 用于渲染的数据
     * @property {String Number} add-time 单条数据添加到队列的时间间隔，单位ms，见上方注意事项说明（默认200）
     * @property {String Number} columns 瀑布流列数，默认为2，设置为auto时自动根据屏幕宽度调整列数
     * @example <u-waterfall :flowList="flowList"></u-waterfall>
     */
    import { mpMixin } from '../../libs/mixin/mpMixin';
	import { mixin } from '../../libs/mixin/mixin';
    import { sleep } from '../../libs/function/index';
    export default {
        name: "u-waterfall",
        props: {
            // #ifdef VUE2
            value: {
                // 瀑布流数据
                type: Array,
                required: true,
                default: function() {
                    return [];
                }
            },
            // #endif
            // #ifdef VUE3
            modelValue: {
                // 瀑布流数据
                type: Array,
                required: true,
                default: function() {
                    return [];
                }
            },
            // #endif
            // 每次向结构插入数据的时间间隔，单位ms
            // 单位ms
            addTime: {
                type: [Number, String],
                default: 200
            },
            // id值，用于清除某一条数据时，根据此idKey名称找到并移除，如数据为{idx: 22, name: 'lisa'}
            // 那么该把idKey设置为idx
            idKey: {
                type: String,
                default: 'id'
            },
            // 瀑布流列数
            columns: {
                type: [Number, String],
                default: 2
            },
            // 瀑布流最小列数
            columnsMin: {
                type: [Number, String],
                default: 2
            },
            // 最小列宽
            minColumnWidth: {
                type: Number,
                default: 230
            }
        },
        mixins: [mpMixin, mixin],
        data() {
            return {
                columnList: [[]], // 存储每列的数据
                children: [],
                // 用于标记是否已经初始化
                initialized: false,
                windowWidth: 375,
                windowHeight: 0
            }
        },
        watch: {
            copyFlowList: {
                handler(nVal, oVal) {
                    if (!nVal || nVal.length == 0) {
                        this.clear(false);
                    } else {
                        if (this.columnList.length == 1) {
                            this.initColumnList()
                        }
                        // 取差值，即这一次数组变化新增的部分
                        let startIndex = Array.isArray(oVal) && oVal.length > 0 ? oVal.length : 0;
                        // 直接处理数据，不再使用tempList和splitData
                        this.handleData(nVal.slice(startIndex));
                    }
                },
                immediate: true
            },
            columns: {
                handler() {
                    this.initColumnList();
                    // 重新分配数据
                    if (this.copyFlowList.length > 0) {
                        this.redistributeData();
                    }
                },
                immediate: false
            }
        },
        created() { 
            this.initColumnList();
        },
        mounted() {
            this.initialized = true;
            // 添加窗口大小变化监听
            // #ifdef H5
            if (this.columns === 'auto') {
                uni.onWindowResize(this.handleWindowResize);
            }
            // #endif
        },
        // 添加beforeUnmount生命周期清理事件监听
        // #ifdef VUE3
        beforeUnmount() {
            // #ifdef H5
            if (this.columns === 'auto') {
                uni.offWindowResize(this.handleWindowResize);
            }
            // #endif
        },
        // #endif
        // #ifdef VUE2
        beforeDestroy() {
            // #ifdef H5
            if (this.columns === 'auto') {
                window.removeEventListener('resize', this.handleWindowResize);
            }
            // #endif
        },
        // #endif
        computed: {
            // 破坏flowList变量的引用，否则watch的结果新旧值是一样的
            copyFlowList() {
                // #ifdef VUE3
                if (!this.modelValue || this.modelValue.length == 0) {
                    // console.log('clear');
                    return [];
                } else {
                    return this.cloneData(this.modelValue);
                }
                // #endif
                // #ifdef VUE2
                return this.cloneData(this.value);
                // #endif
            }
        },
        emits: ['update:modelValue'],
        methods: {
            // 初始化列数据数组
            initColumnList() {
                this.windowWidth = uni.getSystemInfoSync().windowWidth;
                const cols = this.getColumnsCount();
                // console.log(cols)
                this.columnList = Array.from({ length: cols }, () => []);
            },
            
            // 获取列数，支持auto模式
            getColumnsCount() {
                if (this.columns === 'auto') {
                    // 列间距为10rpx(约等于7px)
                    const columnGap = 7;
                    // 计算可容纳的列数
                    let columnCount = Math.max(1, Math.floor(this.windowWidth / (this.minColumnWidth + columnGap)));
                    if (columnCount < this.columnsMin) {
                        columnCount = this.columnsMin
                    }
                    return columnCount;
                }
                return parseInt(this.columns) || 2;
            },
            
            // 窗口大小变化处理函数
            handleWindowResize(res) {
                this.windowWidth = res.size.windowWidth
                this.windowHeight = res.size.windowHeight
                // 防抖处理，避免频繁触发
                if (this.resizeTimer) {
                    clearTimeout(this.resizeTimer);
                }
                this.resizeTimer = setTimeout(() => {
                    const newColumnsCount = this.getColumnsCount();
                    const oldColumnsCount = this.columnList.length;
                    
                    // 只有列数发生变化时才重新分配数据
                    if (newColumnsCount !== oldColumnsCount) {
                        this.redistributeData();
                    }
                }, 300);
            },
            
            // 重新分配所有数据
            async redistributeData() {
                // 清空所有列
                this.initColumnList();
                // 保存所有数据
                const allData = this.cloneData(this.copyFlowList);
                // 重新分配数据
                this.handleData(allData);
            },
            
            // 处理新增数据
            async handleData(newData) {
                if (!newData || newData.length === 0) return;
                
                // 初始化列高度数组
                const columnHeights = new Array(this.columnList.length).fill(0);
                
                // 获取各列当前高度
                for (let i = 0; i < this.columnList.length; i++) {
                    try {
                        const rect = await this.$uGetRect(`#u-column-${i}`);
                        // console.log(`#u-column-${i}`, rect.height)
                        columnHeights[i] = rect.height || 0;
                    } catch (e) {
                        columnHeights[i] = 0;
                    }
                }
                
                // 分配新数据到最短的列
                for (let item of newData) {
                    const minHeightIndex = columnHeights.indexOf(Math.min(...columnHeights));
                    // console.log('this.columnList', this.columnList)
                    this.columnList[minHeightIndex].push(item);
                    
                    // 获取实际渲染后的元素高度而不是估算
                    await sleep(this.addTime)
                    await this.$nextTick(async () => {
                    try {
                        const rect = await this.$uGetRect(`#u-column-${minHeightIndex}`);
                        // console.log(`#u-column-${minHeightIndex}`, rect.height)
                        if (rect.height) {
                            columnHeights[minHeightIndex] = rect.height
                        }
                    } catch (e) {
                        // console.log(e)
                        // columnHeights[i] = 0;
                    }
                    });
                    // this.$nextTick(async () => {
                    //     try {
                    //         // 等待DOM更新后获取实际高度
                    //         const lastIndex = this.columnList[minHeightIndex].length - 1;
                    //         const el = this.$refs[`u-column-${minHeightIndex}`][0].children[lastIndex];
                    //         if (el) {
                    //             const rect = await this.$uGetRect(el);
                    //             const actualHeight = rect.height || 100;
                    //             columnHeights[minHeightIndex] += actualHeight;
                    //         } else {
                    //             // 备用方案：如果无法获取实际高度，则使用默认值
                    //             columnHeights[minHeightIndex] += 100;
                    //         }
                    //     } catch (e) {
                    //         // 出错时使用默认高度
                    //         console.log(e)
                    //         columnHeights[minHeightIndex] += 100;
                    //     }
                    // });
                }
            },

            // 复制而不是引用对象和数组
            cloneData(data) {
                return JSON.parse(JSON.stringify(data));
            },
            
            // 清空数据列表
            clear(bak = true) {
                this.initColumnList();
                // 同时清除父组件列表中的数据
                if (bak) {
                    // #ifdef VUE2
                    this.$emit('input', []);
                    // #endif
                    // #ifdef VUE3
                    this.$emit('update:modelValue', []);
                    // #endif
                }
            },
            
            // 清除某一条指定的数据，根据id实现
            remove(id) {
                // 遍历所有列查找并删除数据
                for (let i = 0; i < this.columnList.length; i++) {
                    const index = this.columnList[i].findIndex(val => val[this.idKey] == id);
                    if (index !== -1) {
                        this.columnList[i].splice(index, 1);
                        break;
                    }
                }
                
                // 同时清除父组件的数据中的对应id的条目
                // #ifdef VUE2
                const valueIndex = this.value.findIndex(val => val[this.idKey] == id);
                if (valueIndex !== -1) {
                    const newValue = this.cloneData(this.value);
                    newValue.splice(valueIndex, 1);
                    this.$emit('input', newValue);
                }
                // #endif
                // #ifdef VUE3
                const modelValueIndex = this.modelValue.findIndex(val => val[this.idKey] == id);
                if (modelValueIndex !== -1) {
                    const newModelValue = this.cloneData(this.modelValue);
                    newModelValue.splice(modelValueIndex, 1);
                    this.$emit('update:modelValue', newModelValue);
                }
                // #endif
            },
            
            // 修改某条数据的某个属性
            modify(id, key, value) {
                let found = false;
                let targetItem = null;
                
                // 在所有列中查找数据
                for (let i = 0; i < this.columnList.length; i++) {
                    const index = this.columnList[i].findIndex(val => val[this.idKey] == id);
                    if (index !== -1) {
                        // 修改对应key的值
                        this.columnList[i][index][key] = value;
                        targetItem = this.columnList[i][index];
                        found = true;
                        break;
                    }
                }
                
                if (found && targetItem) {
                    // 修改父组件的数据中的对应id的条目
                    // #ifdef VUE2
                    const valueIndex = this.value.findIndex(val => val[this.idKey] == id);
                    if (valueIndex !== -1) {
                        let data = this.cloneData(this.value);
                        data[valueIndex][key] = value;
                        this.$emit('input', data);
                    }
                    // #endif
                    // #ifdef VUE3
                    const modelValueIndex = this.modelValue.findIndex(val => val[this.idKey] == id);
                    if (modelValueIndex !== -1) {
                        let data = this.cloneData(this.modelValue);
                        data[modelValueIndex][key] = value;
                        this.$emit('update:modelValue', data);
                    }
                    // #endif
                }
            }
        }
    }
</script>

<style lang="scss" scoped>
    .u-waterfall {
        @include flex;
        flex-direction: row;
        align-items: flex-start;
    }

    .u-column {
        @include flex;
        flex: 1;
        flex-direction: column;
        overflow: hidden;
        /* #ifndef APP-NVUE */
        height: 100%;
        /* #endif */
        // 添加列之间的间距
        &:not(:first-child) {
            margin-left: 10rpx;
        }
    }

    .u-image {
        /* #ifndef APP-NVUE */
        max-width: 100%;
        /* #endif */
    }
</style>