<template>
    <view class="flex-1 fx-row fx-end-cen gap-10" @click="handleClick">
        <view v-if="valueMode" class="text-sm">{{ display }}</view>
        <view v-else class="text-sm text-light">{{ placeholder }}</view>
        <uv-icon name="arrow-down"/>
        <uv-picker ref="picker" :columns="columns" :default-index="defaultIndex" :title="title" :key-name="labelProp"
                   @confirm="handleConfirm" @change="handleChange"/>
    </view>
</template>

<script setup>
import {computed, getCurrentInstance, ref} from 'vue'
import {empty} from "@/uni_modules/uv-ui-tools/libs/function/test";
import _ from "lodash";
import {createPropDefine} from "@/utils";
import {findTreePath} from "@/utils/tree-helper";
import {autoFormValidate} from "@/utils/uni-helper";

const picker = ref(null)
const props = defineProps({
    title: createPropDefine(''),
    placeholder: createPropDefine(''),
    data: createPropDefine([], Array),
    modelValue: createPropDefine(null, [String, Number, Object]),
    labelProp: createPropDefine(''),
    valueProp: createPropDefine(''),
    emptyDisplay: createPropDefine(''),
    treeProp: createPropDefine('')
})
const emits = defineEmits(['change', 'update:modelValue'])

const instance = getCurrentInstance()
const valueMode = computed(() => !empty(props.modelValue) || !!props.emptyDisplay)
const display = computed(() => {
    if (empty(props.modelValue) && !!props.emptyDisplay) return props.emptyDisplay
    return getLabel(current.value) || props.emptyDisplay
})

const currentPath = computed(() => findTreePath(props.data, item => getValue(item) == props.modelValue, props.treeProp))
const current = computed(() => _.last(currentPath.value))
const columns = ref([])
const defaultIndex = ref([])

const handleClick = function () {
    setDefaultColumnsAndIndexs()
    picker.value.open()
}

// columnIndex 正在改变的列 > index 改变后的序号 > indexs 当前选中的全部序号
// > value 当前选中的全部元素 > values 当前columns
const handleConfirm = function ({value}) {
    const selected = _.last(value)
    const selectedValue = getValue(selected)
    emits('update:modelValue', selectedValue)
    emits('change', selected)

    // try trigger uv-form validate
    autoFormValidate(instance, 'change')
}

const handleChange = function ({columnIndex, value}) {
    if (!props.treeProp) return // 不是树形结构
    if (columnIndex == value.length - 1) return // 操作的是最后一列
    const changToValue = getValue(value[columnIndex])
    const {cols, idxes} = calculateColumnsAndIndexs(changToValue)
    console.log('calculateColumnsAndIndexs', cols, idxes)
    columns.value = cols
    picker.value.setIndexs(idxes, true)
}

const setDefaultColumnsAndIndexs = function () {
    const {cols, idxes} = calculateColumnsAndIndexs(props.modelValue)
    columns.value = cols
    defaultIndex.value = idxes
}

/*
* @description 根据给定的值计算picker所需要的columns和indexs
* */
const calculateColumnsAndIndexs = function (value, autoEnd = true) {
    const {data, treeProp} = props
    const cols = []
    const idxes = []
    const path = findTreePath(data, n => getValue(n) == value, treeProp)
    // auto end // 指定的条件，可能查出来的是中间某列的值，此时自动帮它选中至最后一列
    if (autoEnd && treeProp && path?.length) {
        let final = _.last(path)
        while (final[treeProp]?.length) {
            final = final[treeProp][0]
            path.push(final)
        }
    }
    // modelValue logic
    let prevNode = data
    _.forEach(path, item => {
        const idx = prevNode.findIndex(n => getValue(n) == getValue(item))
        if (idx < 0) {
            // 无效值，停止迭代
            cols.length = 0
            idxes.length = 0
            return false // lodash.forEach接收到false返回会终止迭代
        }
        cols.push(prevNode)
        idxes.push(idx)
        prevNode = _.get(prevNode, idx + '.' + treeProp)
    })
    // default logic
    if (!cols.length && data.length) {
        prevNode = data
        do {
            cols.push(prevNode)
            idxes.push(0)
            prevNode = _.get(prevNode, '0.' + props.treeProp)
        } while (prevNode)
    }
    return {cols, idxes}
}

const getValue = item => _.get(item, props.valueProp, item)
const getLabel = item => _.get(item, props.labelProp, item)

defineExpose({current, currentPath})
</script>

<style scoped>

</style>