<template>
  <div id="popover" ref="bubbleRef" class="ui-popover">
    <view
      :id="popoverBoxId"
      class="popover-box"
      @touchend="onTouchend"
      @touchstart="onTouchstart"
    >
      <slot></slot>
    </view>
    <!-- mode -->
    <view
      @click.stop="close(50)"
      :id="popoverContentId"
      class="popover-content"
      :style="data.showStyle"
    >
      <div class="menu">
        <div
          class="w-full h-[132rpx] text-[24rpx] text-[#FFFFFF] flex items-center justify-around"
        >
          <div
            v-if="props.isShowCopy"
            @click="() => itemClick('actionCopy')"
            class="flex flex-col items-center justify-center"
          >
            <tm-image :width="40" :height="40" :src="copy07"></tm-image>
            <div class="mt-1">复制</div>
          </div>
          <div
            v-if="props.isShowConvertText"
            @click="() => itemClick('convertText')"
            class="flex flex-col items-center justify-center"
          >
            <tm-image :width="40" :height="40" :src="copy07"></tm-image>
            <div class="mt-1">转文字</div>
          </div>
          <div
            @click="() => itemClick('multipleChoose')"
            class="flex flex-col items-center justify-center"
          >
            <tm-image
              :width="40"
              :height="40"
              :src="multipleChoices"
            ></tm-image>
            <div class="mt-1">多选</div>
          </div>
          <div
            v-if="props.isShowCite"
            @click="() => itemClick('actionCite')"
            class="flex flex-col items-center justify-center"
          >
            <tm-image :width="40" :height="40" :src="cite"></tm-image>
            <div class="mt-1">引用</div>
          </div>
          <div
            v-if="props.isShowWithdraw"
            @click="() => itemClick('actionWithdraw')"
            class="flex flex-col items-center justify-center"
          >
            <tm-image :width="40" :height="40" :src="withdraw"></tm-image>
            <div class="mt-1">撤回</div>
          </div>
          <div
            @click="() => itemClick('actionDelete')"
            class="flex flex-col items-center justify-center"
          >
            <tm-image :width="40" :height="40" :src="delete07"></tm-image>
            <div class="mt-1">删除</div>
          </div>
        </div>
        <div :style="data.iconStyle" class="icon"></div>
      </div>
    </view>
    <view
      v-show="data.popoverShow"
      @touchstart="close"
      @click="close"
      class="popover-bg"
    ></view>
  </div>
</template>

<script setup>
// 组件

// uniapp & vue
import { onLoad, onReady } from '@dcloudio/uni-app'
import { defineEmits, defineProps } from 'vue'
import {
  reactive,
  ref,
  watch,
  computed,
  nextTick,
  getCurrentInstance,
  onMounted,
  onBeforeUnmount,
} from 'vue'
import copy07 from '@/static/image/chatList/copy07@2x.png'
import multipleChoices from '@/static/image/chatList/multipleChoices@2x.png'
import cite from '@/static/image/chatList/cite@2x.png'
import withdraw from '@/static/image/chatList/withdraw@2x.png'
import delete07 from '@/static/image/chatList/delete@2x.png'

// pinia
const systemInfo = uni.getSystemInfoSync()
const bubbleRef = ref(null)

const props = defineProps({
  isShowCopy: {
    type: Boolean,
    default: true,
  },
  isShowCite: {
    type: Boolean,
    default: true,
  },
  isShowWithdraw: {
    type: Boolean,
    default: true,
  },
  isShowConvertText: {
    //是否显示转文字
    type: Boolean,
    default: false,
  },
})

const emits = defineEmits(['clickMenu'])

/**
 * @name  生成UUID
 */
const uuid = () => {
  const reg = /[xy]/g
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
    .replace(reg, function (c) {
      var r = (Math.random() * 16) | 0,
        v = c == 'x' ? r : (r & 0x3) | 0x8
      return v.toString(16)
    })
    .replace(/-/g, '')
}

const popoverBoxId = `ID${uuid()}`
const popoverContentId = `ID${uuid()}`
const instance = getCurrentInstance()
const data = reactive({
  popoverShow: false,
  defaultStyle: {},
  showStyle: {
    left: 0,
    right: '',
    transform: '',
  },
  iconStyle: {
    left: '',
    right: '',
    transform: '',
  },
})

/**
 * @name  获取DOM
 */
const getDom = (dom) => {
  return new Promise((resolve, reject) => {
    const query = uni.createSelectorQuery().in(instance)
    let select = query.select(dom)
    const boundingClientRect = select.boundingClientRect((data) => {
      resolve(data)
    })
    boundingClientRect.exec()
  })
}

const itemClick = (item) => {
  emits('clickMenu', item)
}

// 弹起 长按5
let pressDownTime = 0
let time = null
const onTouchstart = () => {
  time && clearTimeout(time)
  time = setTimeout(open, 500)
}

const onTouchend = () => {
  time && clearTimeout(time)
}

const open = async () => {
  let popoverContent = await getDom(`#${popoverContentId}`)
  let popoverBox = await getDom(`#${popoverBoxId}`)

  // 缩放中心点
  let originX = popoverBox.width / 2
  // 根据距离 初始化位置 判断是顶部还是底部
  let isTop = popoverBox.top - 50 > popoverContent.height
  // 上面还是下面
  data.defaultStyle = {
    top: isTop ? '60rpx' : 'auto',
    bottom: !isTop ? '-20rpx' : 'auto',
    transform: `translateY(${isTop ? '-100%' : '100%'}) scale(.8)`,
  }
  // 左边还是右边
  if (popoverBox.left > systemInfo.windowWidth - popoverBox.right) {
    data.defaultStyle.right = 0
    // 动画缩放中心点
    data.defaultStyle['transform-origin'] = `${
      popoverContent.width - originX
    }px ${isTop ? '100%' : '0%'}`
  } else {
    data.defaultStyle.left = 0
    // 动画缩放中心点
    data.defaultStyle['transform-origin'] = `${originX}px ${
      isTop ? '100%' : '0%'
    }`
  }
  data.showStyle = { ...data.defaultStyle }
  // icon位置样式
  let iconDefsultStyle = {
    transform: `translate(0%, ${isTop ? '20%' : '-20%'})`,
    'border-top-color': isTop ? '#333333' : '',
    'border-bottom-color': !isTop ? '#333333' : '',
    top: !isTop ? '-20rpx' : 'auto',
    bottom: isTop ? '-20rpx' : 'auto',
  }

  setTimeout(() => {
    if (popoverBox.left > systemInfo.windowWidth - popoverBox.right) {
      data.showStyle = {
        // 位置
        ...data.defaultStyle,
        // 显示
        opacity: 1,
        transform: `translateY(${isTop ? '-100%' : '100%'}) scale(1)`,
        'pointer-events': 'auto',
      }
      data.iconStyle = {
        right: `${originX}px`,
        left: 'auto',
        ...iconDefsultStyle,
      }
    } else {
      data.showStyle = {
        // 位置
        ...data.defaultStyle,
        // 显示
        opacity: 1,
        transform: `translateY(${isTop ? '-100%' : '100%'}) scale(1)`,
        'pointer-events': 'auto',
      }
      data.iconStyle = {
        left: `${originX}px`,
        right: 'auto',
        ...iconDefsultStyle,
      }
    }

    if (!data.popoverShow) data.popoverShow = true
  }, 200)
}

const close = (time) => {
  setTimeout(() => {
    data.popoverShow = false
    data.showStyle = data.defaultStyle
  }, time || 0)
}
const handleClickOutside = (event) => {
  if ((data.popoverShow = false)) {
    return false
  }
  if (bubbleRef.value && !bubbleRef.value.contains(event.target)) {
    close()
  }
}
onMounted(() => {
  document.addEventListener('click', handleClickOutside)
})

onBeforeUnmount(() => {
  document.removeEventListener('click', handleClickOutside)
})
</script>

<style lang="scss" scoped>
.ui-popover {
  position: relative;
  .popover-box {
    width: fit-content;
  }
  .popover-content {
    width: fit-content;
    transition: all 0.2s;
    z-index: 5;
    position: absolute;
    top: 0;
    opacity: 0;
    pointer-events: none;
  }

  .popover-bg {
    width: 100%;
    height: 100%;
    position: fixed;
    left: 0;
    top: 0;
    z-index: 4;
  }

  .menu {
    width: 526rpx;
    height: 132rpx;
    display: flex;
    background-color: #333333;
    display: flex;
    color: #fff;
    border-radius: 15rpx;
    font-size: 26rpx;
    padding: 0 10rpx;
    box-sizing: border-box;
    position: relative;
    .icon {
      border: 15rpx solid transparent;
      position: absolute;
    }
    .item {
      flex: 1;
      height: 120rpx;
      text-align: center;
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
    }
    image {
      width: 26rpx;
      height: 26rpx;
      margin-bottom: 8rpx;
    }
  }
}
</style>
