<template>
    <view class="ui-fixed">
        <view
            class="ui-fixed-box"
            :id="`fixed-${uuid}`"
            :class="[{ fixed: state.fixed }]"
            :style="[
                {
                    left: sticky ? 'auto' : '0px',
                    top: state.fixed && !bottom ? (noNav ? val : val + sys_navBar) + 'px' : 'auto',
                    bottom: insetHeight,
                    zIndex: index + peach.$zIndex.navbar,
                },
                !alway ? { opacity: state.opacityVal } : '',
            ]"
        >
            <view class="ui-fixed-content" @tap="toTop" :style="[{ zIndex: index + peach.$zIndex.navbar }]">
                <slot></slot>
                <view
                    v-if="safeAreaInsets.bottom && bottom && isInset"
                    class="inset-bottom"
                    :style="[{ height: safeAreaInsets.bottom + 'px' }]"
                ></view>
            </view>
            <view class="ui-fixed-bottom" :class="[bg]" v-if="bottom"></view>
            <view
                class="ui-fixed-bg"
                :class="[ui, bg]"
                :style="[
                    { zIndex: index + peach.$zIndex.navbar - 1 },
                    bgStyles,
                    opacity ? { opacity: state.opacityVal } : '',
                ]"
            ></view>
        </view>
        <view
            class="skeleton"
            :style="[{ height: state.content.height + 'px', width: width + 'px' }]"
            v-if="sticky ? state.fixed : placeholder && state.fixed"
        ></view>
    </view>
</template>

<script setup>
import { onPageScroll } from '@dcloudio/uni-app'
import { getCurrentInstance, unref, onMounted, reactive, nextTick, computed } from 'vue'
import peach from '@/peach'
const { safeAreaInsets } = peach.$platform.device

const vm = getCurrentInstance()

const uuid = peach.$helper.guid()
const sys_navBar = peach.$platform.navBar
const state = reactive({
    content: {},
    fixed: true,
    scrollTop: 0,
    opacityVal: 0,
})
const insetHeight = computed(() => {
    if (state.fixed && props.bottom) {
        if (props.isInset) {
            return props.val + 'px'
        } else {
            return props.val + safeAreaInsets.bottom + 'px'
        }
    } else {
        return 'auto'
    }
})
const props = defineProps({
    noNav: {
        type: Boolean,
        default: false,
    },
    bottom: {
        type: Boolean,
        default: false,
    },
    bg: {
        type: String,
        default: '',
    },
    bgStyles: {
        type: Object,
        default() {},
    },
    val: {
        type: Number,
        default: 0,
    },
    width: {
        type: [String, Number],
        default: 0,
    },
    alway: {
        type: Boolean,
        default: true,
    },
    opacity: {
        type: Boolean,
        default: false,
    },
    index: {
        type: [Number, String],
        default: 0,
    },
    placeholder: {
        type: [Boolean],
        default: false,
    },
    sticky: {
        type: [Boolean],
        default: false,
    },
    noFixed: {
        type: Boolean,
        default: false,
    },
    ui: {
        type: String,
        default: '',
    },
    clickTo: {
        type: Boolean,
        default: false,
    },
    //是否需要安全区
    isInset: {
        type: Boolean,
        default: true,
    },
})

state.fixed = !unref(props.sticky)
onPageScroll((e) => {
    let top = e.scrollTop
    state.scrollTop = top
    state.opacityVal = top > peach.$platform.navbar ? 1 : top * 0.01
})

onMounted(() => {
    nextTick(() => {
        computedQuery()
    })
})

const computedQuery = () => {
    uni.createSelectorQuery()
        .in(vm)
        .select(`#fixed-${uuid}`)
        .boundingClientRect((data) => {
            if (data != null) {
                state.content = data
                if (unref(props.sticky)) {
                    setFixed(state.scrollTop)
                }
            }
        })
        .exec()
}

const setFixed = (value) => {
    if (unref(props.bottom)) {
        state.fixed =
            value >=
            state.content.bottom - peach.$platform.device.windowHeight + state.content.height + unref(props.val)
    } else {
        state.fixed =
            value >=
            state.content.top - (unref(props.noNav) ? unref(props.val) : unref(props.val) + peach.$platform.navbar)
    }
}

const toTop = () => {
    if (props.hasToTop) {
        uni.pageScrollTo({
            scrollTop: state.content.top,
            duration: 100,
        })
    }
}
</script>

<style lang="scss">
.ui-fixed {
    .ui-fixed-box {
        position: relative;
        width: 100%;
        &.fixed {
            position: fixed;
        }
        .ui-fixed-content {
            position: relative;
        }
        .ui-fixed-bg {
            position: absolute;
            width: 100%;
            height: 100%;
            top: 0;
            z-index: 1;
            pointer-events: none;
        }
    }
}
.inset-bottom {
    background: #fff;
}
</style>
