<template>
    <view
        class="floating-drag"
        :style="{
            left: formatCssValue(buttonPosition.left),
            right: formatCssValue(buttonPosition.right),
            bottom: formatCssValue(buttonPosition.bottom),
            width: width + 'rpx',
            height: height + 'rpx',
            display: visible ? 'block' : 'none',
        }"
        @touchstart="touchStart"
        @touchmove="touchMove"
        @touchend="touchEnd"
        @click="handleClick"
        v-if="visible"
    >
        <slot> </slot>
    </view>
</template>

<script>
export default {
    name: "FloatingDrag",
    props: {
        // 初始位置
        initialPosition: {
            type: Object,
            default: () => ({
                left: "auto",
                right: 0,
                bottom: "20%",
            }),
        },
        // 组件尺寸
        width: {
            type: [Number, String],
            default: 120,
        },
        height: {
            type: [Number, String],
            default: 120,
        },
        // 是否显示
        visible: {
            type: Boolean,
            default: true,
        },
        // 点击事件
        onClick: {
            type: Function,
            default: null,
        },
    },
    data() {
        return {
            // 悬浮按钮位置
            buttonPosition: {
                left: "auto",
                right: 0,
                bottom: "20%",
            },
            // 触摸开始位置
            startX: 0,
            startY: 0,
            // 屏幕宽度和高度
            screenWidth: 0,
            screenHeight: 0,
            // 初始位置记录，用于计算拖动
            initialLeft: 0,
            initialBottom: 0,
            // 是否正在更新位置，用于防止频繁更新
            isUpdatingPosition: false,
        };
    },
    created() {
        // 使用传入的初始位置
        this.buttonPosition = { ...this.initialPosition };
    },
    watch: {
        initialPosition: {
            handler(newVal) {
                this.buttonPosition = { ...newVal };
                console.log(newVal,'newVal')
            },
            immediate: true,
            deep: true,
        },
    },
    mounted() {
        // 获取屏幕宽度和高度
        uni.getSystemInfo({
            success: (res) => {
                this.screenWidth = res.windowWidth;
                this.screenHeight = res.windowHeight;
            },
        });
    },
    methods: {
        // 格式化CSS值，只在需要时添加px单位
        formatCssValue(value) {
            // 如果是数字，添加px单位
            if (typeof value === 'number') {
                return value + 'px';
            }
            
            // 如果是字符串
            if (typeof value === 'string') {
                // 如果已经包含单位（px, %, vh, vw, em, rem等）或是auto, inherit等特殊值，直接返回
                if (value === 'auto' || 
                    value === 'inherit' || 
                    value.includes('%') || 
                    value.includes('px') || 
                    value.includes('vh') || 
                    value.includes('vw') || 
                    value.includes('em') || 
                    value.includes('rem')) {
                    return value;
                }
                
                // 如果是纯数字字符串，添加px单位
                if (!isNaN(Number(value))) {
                    return value + 'px';
                }
            }
            
            // 其他情况，返回原值
            return value;
        },

        // 触摸开始
        touchStart(e) {
            const touch = e.touches[0];
            this.startX = touch.clientX;
            this.startY = touch.clientY;

            // 记录初始位置，用于计算移动距离
            if (this.buttonPosition.right !== "auto") {
                // 如果是靠右定位，记录当前位置但不立即改变显示位置
                this.initialLeft = this.screenWidth - parseFloat(this.width) / 2;
            } else {
                this.initialLeft = parseFloat(this.buttonPosition.left);
            }

            // 如果bottom是百分比，转换为具体像素值
            if (typeof this.buttonPosition.bottom === "string" && this.buttonPosition.bottom.includes("%")) {
                const percentage = parseFloat(this.buttonPosition.bottom) / 100;
                this.initialBottom = this.screenHeight * percentage;
            } else {
                this.initialBottom = parseFloat(this.buttonPosition.bottom);
            }
        },

        // 触摸移动
        touchMove(e) {
            if(!e) return;
            // 阻止默认行为，防止页面滚动
            e.preventDefault && e.preventDefault();
            e.stopPropagation && e.stopPropagation();

            const touch = e.touches[0];

            // 计算移动距离
            const deltaX = touch.clientX - this.startX;
            const deltaY = touch.clientY - this.startY;

            // 使用初始位置计算新位置，避免累积误差
            let newLeft = this.initialLeft + deltaX;
            let newBottom = this.initialBottom - deltaY; // 注意：y轴方向是相反的

            // 获取按钮实际宽度（将rpx转换为px）
            const buttonWidthPx = (parseFloat(this.width) / 750) * this.screenWidth;

            // 确保按钮不超出屏幕边界
            if (newLeft < 0) {
                newLeft = 0;
            } else if (newLeft > this.screenWidth - buttonWidthPx) {
                newLeft = this.screenWidth - buttonWidthPx;
            }

            // 确保按钮不超出屏幕垂直边界
            if (newBottom < 20) {
                newBottom = 20;
            } else if (newBottom > this.screenHeight - buttonWidthPx) {
                newBottom = this.screenHeight - buttonWidthPx;
            }

            // 使用节流方式更新位置，避免过于频繁的更新
            if (!this.isUpdatingPosition) {
                this.isUpdatingPosition = true;

                // 更新位置 - 第一次移动时才真正改变right为auto
                this.buttonPosition = {
                    left: newLeft,
                    right: "auto",
                    bottom: newBottom,
                };

                // 使用setTimeout代替requestAnimationFrame，在微信小程序中更兼容
                setTimeout(() => {
                    this.isUpdatingPosition = false;
                }, 16); // 约等于60fps的刷新率
            }
        },

        // 触摸结束，实现吸附效果
        touchEnd() {
            // 确保不再有待处理的更新
            this.isUpdatingPosition = false;

            // 获取按钮实际宽度（将rpx转换为px）
            const buttonWidthPx = (parseFloat(this.width) / 750) * this.screenWidth;
            const buttonCenter = this.buttonPosition.left + buttonWidthPx / 2; // 按钮中心位置

            const halfScreen = this.screenWidth / 2;

            // 判断是吸附到左边还是右边
            if (buttonCenter < halfScreen) {
                // 吸附到左边
                this.buttonPosition = {
                    left: 0,
                    right: "auto",
                    bottom: this.buttonPosition.bottom,
                };
            } else {
                // 吸附到右边
                this.buttonPosition = {
                    left: "auto",
                    right: 0,
                    bottom: this.buttonPosition.bottom,
                };
            }

            // 触发位置变更事件
            this.$emit("position-change", { ...this.buttonPosition });
        },

        // 处理点击事件
        handleClick() {
            this.$emit("click");
            if (this.onClick) {
                this.onClick();
            }
        },
    },
};
</script>

<style lang="scss" scoped>
.floating-drag {
    position: fixed;
    z-index: 999;
    transition: all 0.3s ease;
}
</style>
