import { ref, onMounted, computed } from 'vue'
import { toRawType } from './'

/**
 * 获取真实DOM的高度
 * @returns [heightRef, VMRef, readyRef]
 */
export const getVMDomWH = attr => {
    const origin = ref(0)
    const domRef = ref(null)
    const ready = ref(false)
    const referWH = () => {
        origin.value = 0
        ready.value = false
        if (domRef.value) {
            setTimeout(() => {
                origin.value = attr === 'width' ? domRef.value.offsetWidth : domRef.value.offsetHeight
                setTimeout(() => (ready.value = true))
            })
        }
    }

    onMounted(referWH)

    return [origin, domRef, ready, referWH]
}

/**
 * 生成切换高度的方法
 * @returns [VMRef, fn, maxHeightRef, originHeightRef, showRef, readyRef]
 */
export const changeWHFactory = (isShow = false, attr = 'height') => {
    const [origin, domRef, ready, referWH] = getVMDomWH(attr)
    const max = ref(0)
    const show = computed({
        get: () => {
            return max.value == origin.value
        },
        set: val => {
            max.value = val ? origin.value : 0
        },
    })
    const changeShow = (val = !show.value) => {
        show.value = val
    }

    onMounted(() => {
        show.value = isShow
    })

    return [domRef, changeShow, max, origin, show, ready, referWH]
}

/**
 * 获取父级滚动
 * @param {*} node
 * @returns
 */
export const getScrollParent = node => {
    if (node == null) {
        return null
    }
    if (node === document.documentElement) {
        return node
    }

    const cssScrollY = getComputedStyle(node).overflowY
    const cssScrollX = getComputedStyle(node).overflowX
    if (node.scrollHeight > node.clientHeight || cssScrollY === 'auto' || cssScrollY === 'scroll' || cssScrollX === 'auto' || cssScrollX === 'scroll') {
        return node
    } else {
        return getScrollParent(node.parentNode)
    }
}

/**
 * 获取所有父级滚动
 * @param {*} origin
 * @param {*} target
 */
export const getScrollParents = (origin, target) => {
    const parents = []
    let temporary = origin
    while (temporary && temporary !== target && temporary !== document.documentElement && target.contains(temporary)) {
        const scrollParent = getScrollParent(temporary)
        if (scrollParent) {
            if (scrollParent !== origin) {
                parents.push(scrollParent)
            }
            temporary = scrollParent.parentNode
        } else {
            break
        }
    }

    return parents
}

/**
 * 获取制定dom在相对于目标中的位置
 * @param {*} origin 或获取的DOM
 * @param {*} target 目标DOM
 * @param {*} isIncludeSelf 是否要包含自身宽高
 * @returns 位置信息 {x, y}
 */
export const getPostionByTarget = (origin, target, isIncludeSelf = false) => {
    const pos = { x: 0, y: 0, width: origin.offsetWidth, height: origin.offsetHeight }

    let temporary = origin
    while (temporary && temporary !== target && temporary !== document.documentElement && target.contains(temporary)) {
        pos.x += temporary.offsetLeft + temporary.clientLeft
        pos.y += temporary.offsetTop + temporary.clientTop
        temporary = temporary.offsetParent
    }

    if (isIncludeSelf) {
        pos.x += pos.width
        pos.y += pos.height
    }
    return pos
}

export const normalizeUnitToStyle = unit => {
    if (unit === void 0) {
        return unit
    } else if (toRawType(unit) === 'Number') {
        return unit ? ((unit <= 1) & (unit >= 0) ? 100 * unit + '%' : unit + 'px') : void 0
    } else if (unit.includes('px')) {
        return normalizeUnitToStyle(parseFloat(unit))
    } else if (unit.includes('%')) {
        return normalizeUnitToStyle(parseFloat(unit) / 100)
    } else {
        return unit
    }
}
