import {array, empty, func} from "@/uni_modules/uv-ui-tools/libs/function/test";
import {useUserStore} from "@/hooks/useUserStore";
import {toValue, computed, ref} from 'vue'
import mxConfig from "@/common/mxConfig";

export const storeGetterFilter = function (userStore, arraySource, refConfig) {
    if (!array(arraySource)) return []
    const results = arraySource.filter(menu => {
        // 不配置认为通配
        if (empty(menu["satisfyStoreGetters"])) return true
        // 过滤掉不满足getters
        const propReader = (getter) => {
            let prop = getter
            let opposite = false
            if (getter.startsWith('!')) {
                prop = getter.substring(1)
                opposite = true
            }
            const propArr = prop.split('.')
            let propResult = userStore
            for (const p of propArr) {
                if ([null, undefined].includes(propResult)) break
                propResult = toValue(propResult[p])
            }
            return !opposite ? propResult : !propResult
        }
        return !menu["satisfyAny"] ?
            menu["satisfyStoreGetters"].every?.(propReader) :
            menu["satisfyStoreGetters"].some?.(propReader)
    })
    return refConfig ?
        results.map(r => mergeConfigFn(userStore, r, refConfig)) :
        results
}

/*
* 内部方法，合并带方法的配置文件，此方法在storeGetterFilter内部运行才有意义。
* 不对外暴露此方法。
* */
const mergeConfigFn = function (userStore, obj, refConfig) {
    const target = {}
    Object.keys(obj).forEach(prop => {
        let val = obj[prop]
        if (func(val)) // 传入目标方法，以供方法内部引用同源参数，即方法内部可以和这里达到同样的运行结果。
            val = val(userStore, storeGetterFilter, refConfig)
        else if (array(val) && val.some(item => item && item['satisfyStoreGetters']))
            val = storeGetterFilter(userStore, val, refConfig)
        target[prop] = val
    })
    return target
}
export const useUserStorePageFilter = function (pageName) {
    // const data
    const propBanner = `index${pageName}Banner`
    const propMenu = `index${pageName}Menus`
    const propBlock = `index${pageName}Blocks`
    const propHeaderOption = `index${pageName}HeaderOption`

    // reactive data
    const userStore = useUserStore()
    const bannerImage = computed(() => mxConfig[propBanner])
    const menus = computed(() => storeGetterFilter(userStore, mxConfig[propMenu]))
    const blocks = computed(() => storeGetterFilter(userStore, mxConfig[propBlock], mxConfig))
    const headerOption = computed(() => mxConfig[propHeaderOption])

    return {
        bannerImage,
        menus,
        blocks,
        headerOption
    }
}
