<template>
    <view class="design-picker">
        <picker-view
            :value="innerIndex"
            :immediate-change="immediateChange"
            class="u-picker__view"
            indicator-style="height: 44px;`"
            @change="changeHandler"
        >
            <picker-view-column
                v-for="(item, index) in columns"
                :key="index"
                class="u-picker__view__column"
            >
                <view
                    class="u-picker__view__column__item u-line-1"
                    v-for="(item1, index1) in item"
                    :key="index1"
                    :style="columnItemStyle"
                >
                    {{ item1 }}
                </view>
            </picker-view-column>
        </picker-view>
        <view class="design-picker-footer">
            <slot name="toolbar" />
        </view>
    </view>
</template>

<script setup lang="ts">
import _ from 'lodash'
import { computed, ref, watch } from 'vue'

const props = defineProps({
    columns: {
        type: Array,
        default: () => []
    },
    immediateChange: {
        type: Boolean,
        default: true
    },
    itemHeight: {
        type: Number,
        default: 44
    },
    defaultIndex: {
        type: Array,
        default: () => []
    }
})
const emit = defineEmits(['update:modelValue', 'change'])

const innerIndex = ref<number[]>([]) // 索引值 ，对应picker-view的value
const lastIndex = ref([]) // 上一次选择的列索引
const lastColumnIndex = ref(0) // 上一次的变化列索引
const innerColumns = ref([]) // 各列的值
const inputeValue = computed(() => {
    const items = innerColumns.value.map((item, index) => item[innerIndex.value[index]])
    return items
})
const columnItemStyle = computed(() => {
    const { itemHeight } = props
    return {
        height: addUnit(itemHeight, 'rpx'),
        lineHeight: addUnit(itemHeight, 'rpx'),
        display: 'block'
    }
})

const changeHandler = e => {
    const { value } = e.detail
    let index = 0,
        columnIndex = 0
    // 通过对比前后两次的列索引，得出当前变化的是哪一列
    for (let i = 0; i < value.length; i++) {
        const item = value[i]
        if (item !== (lastIndex.value[i] || 0)) {
            // 把undefined转为合法假值0
            // 设置columnIndex为当前变化列的索引
            columnIndex = i
            // index则为变化列中的变化项的索引
            index = item
            break // 终止循环，即使少一次循环，也是性能的提升
        }
    }
    lastColumnIndex.value = columnIndex
    const values = innerColumns.value

    setLastIndex(value)
    setIndexs(value)
    emit('update:modelValue', inputeValue.value)
    emit('change', {
        value: innerColumns.value.map((item, index) => item[value[index]]),
        index,
        indexs: value,
        // values为当前变化列的数组内容
        values,
        columnIndex
    })
}
// 设置index索引
const setIndexs = (index, flag: boolean) => {
    innerIndex.value = _.cloneDeep(index)
    if (flag) {
        setLastIndex(index)
    }
}
// 记录上一次的各列索引位置
const setLastIndex = index => {
    lastIndex.value = _.cloneDeep(index)
}

// 设置整体各列的columns的值
const setColumns = columns => {
    innerColumns.value = _.cloneDeep(columns)
    // 如果在设置各列数据时，没有被设置默认的各列索引defaultIndex，那么用0去填充它，数组长度为列的数量
    if (innerIndex.value.length === 0) {
        innerIndex.value = new Array(columns.length).fill(0)
    }
}

watch(
    () => props.columns,
    newVal => {
        setColumns(newVal)
    },
    { immediate: true, deep: true }
)
// 设置默认值为当前时间
watch(
    () => props.defaultIndex,
    newVal => {
        setIndexs(newVal, true)
    },
    { immediate: true, deep: true }
)
/**
 * @description 添加单位，如果有rpx，upx，%，px等单位结尾或者值为auto，直接返回，否则加上px单位结尾
 * @param {string|number} value 需要添加单位的值
 * @param {string} unit 添加的单位名 比如px
 */
function addUnit(value = 'auto', unit = 'px') {
    if (unit == 'rpx' && number(String(value))) {
        value = value * 2
    }
    value = String(value)
    // 用内置验证规则中的number判断是否为数值
    return number(value) ? `${value}${unit}` : value
}
/**
 * 验证十进制数字
 */
function number(value) {
    return /^[\+-]?(\d+\.?\d*|\.\d+|\d\.\d+e\+\d+)$/.test(value)
}
</script>

<style lang="scss" scoped>
.design-picker {
    display: flex;
    flex-direction: column;
    .u-picker {
        position: relative;

        &__view {
            width: 100vw;
            height: 300rpx;
            margin-top: 20rpx;
            &__column {
                display: flex;
                flex: 1;
                justify-content: center;

                &__item {
                    display: flex;
                    justify-content: center;
                    align-items: center;
                    font-size: 32rpx;
                    text-align: center;
                    /* #ifndef APP-NVUE */
                    display: block;
                    /* #endif */
                    color: $u-main-color;

                    &--disabled {
                        /* #ifndef APP-NVUE */
                        cursor: not-allowed;
                        /* #endif */
                        opacity: 0.35;
                    }
                }
            }
        }
    }
    &-footer {
    }
}
</style>
