<template>
  <view class="p_wrapper" style="z-index: 19999" v-if="isShow">
    <view
      ref="mask"
      catchtouchmove="true"
      bubble="true"
      class="mask"
      style="z-index: 20000"
      :style="maskStyle"
      @touchmove.stop.prevent="moveHandle"
      @click="close()"
      :class="[notNvueAni ? 'not_animation_show_mask' : 'not_animation_hide_mask']"
    ></view>
    <view
      ref="popup"
      id="popup"
      class="content"
      :class="{
        not_def_show: type == 'zoom',
        not_def_show_f: type != 'zoom',
        not_nvue_animation_show: notNvueAni && type == 'zoom',
        not_nvue_animation_hide: !notNvueAni && type == 'zoom',
        not_nvue_animation_show_f: notNvueAni && type != 'zoom',
        not_nvue_animation_hide_f: !notNvueAni && type != 'zoom',
      }"
      style="z-index: 20001"
      :style="contentStyle"
    >
      <slot></slot>
    </view>
  </view>
</template>

<script>
// #ifdef APP-PLUS-NVUE
const animation = weex.requireModule('animation')
// #endif
export default {
  name: 'benben-position-popup',
  props: {
    // 是否显示蒙层
    maskHide: {
      type: Boolean,
      default: false,
    },
    // 弹窗模式 有 zoom  fade
    type: {
      type: String,
      default: 'zoom',
    },
    // 内容区 宽度 单位rpx
    width: {
      type: Number,
      default: 0,
    },
    // 内容区 高度 单位 rpx
    height: {
      type: Number,
      default: 0,
    },
    // 弹窗定位 顶部距离  可ref 调用时传入  ref没有传入这个就是默认定位 单位px
    top: {
      type: Number,
      default: 0,
    },
    // 弹窗定位 左侧距离  可ref 调用时传入  ref没有传入这个就是默认定位 单位px
    left: {
      type: Number,
      default: 0,
    },
    // 是否有 原生状态栏
    hasNav: {
      type: Boolean,
      default: false,
    },
    // 自定义弹出方向
    popupOrigin: {
      type: String,
      default: 'left top',
    },
    // 是否 开启自适应
    adaption: {
      type: Boolean,
      default: true,
    },
  },
  data() {
    return {
      origin: 'left top', // 动画的定位点
      x: 0, // 弹窗弹出位置 定位点
      y: 0, // 弹窗弹出位置 定位点
      maxX: 0, // 最大 x 值 用于判断弹窗定位点
      maxY: 0, // 最大 y 值 用于判断弹窗定位点
      winH: 0, // 屏幕 总高度
      winW: 0, // 屏幕 总宽度
      windowTop: 0, // h5 下的顶部距离
      notNvueAni: false, // 控制非nvue动画
      hideTarget: 'scale(0,0)', // 隐藏目标
      isShow: false, // 是否显示
      statusBarHeight: 0, // 手机状态栏高度
    }
  },
  methods: {
    // 一些状态下 阻止 遮罩下滚动
    moveHandle() {
      return
    },
    // 打开弹窗
    async open(e, isMe) {
      console.log('benben-position-popup', e.changedTouches)
      this.comMax()
      let x, y
      if (isMe && e) {
        // 自己传入 x y 定位
        x = e.x
        y = e.y
      } else if (e) {
        // 自动传入长按事件 对象
        // app nvue 的情况 拿取 长按位置
        // #ifdef APP-NVUE
        if (Array.isArray(e.changedTouches) && e.changedTouches.length > 0) {
          // nvue 安卓下 获取pageX pageY 会有问题 所以 统一使用 screenX screenY
          x = e.changedTouches[0].screenX
          y = e.changedTouches[0].screenY - this.statusBarHeight - (this.hasNav ? 40 : 0)
        } else {
          const { position } = e
          x = position.x
          y = position.y
        }
        // #endif
        // app 非nvue 的情况 拿取 长按位置
        // #ifdef APP-VUE
        if (Array.isArray(e.changedTouches) && e.changedTouches.length > 0) {
          x = e.changedTouches[0].clientX
          y = e.changedTouches[0].clientY
          console.log('x', x)
          console.log('y', y)
        } else {
          const { position } = e
          x = position.x
          y = position.y
        }
        // #endif
        // 小程序的 情况 拿取 长按位置
        // #ifdef MP

        x = e.touches[0].clientX
        y = e.touches[0].clientY
        // #endif
        // h5的 情况 拿取 长按位置
        // #ifdef H5
        if (Array.isArray(e.changedTouches) && e.changedTouches.length > 0) {
          x = e.changedTouches[0].clientX
          y = e.changedTouches[0].clientY + this.windowTop
        }
        // #endif
      }
      // 固定定位  props 传入
      if (!e) {
        x = this.left
        y = this.top
      }

      const originArr = this.popupOrigin.split(' ')
      let originX = originArr[0]
      let originY = originArr[1]
      if (this.adaption) {
        if (x > this.maxX && y > this.maxY) {
          // this.origin = 'right bottom';
          originX = 'right'
          originY = 'bottom'
        } else if (x < uni.upx2px(this.width) && y < uni.upx2px(this.height)) {
          originX = 'left'
          originY = 'top'
        } else if (x > this.maxX) {
          originX = 'right'
        } else if (y > this.maxY) {
          originY = 'bottom'
        } else if (x < uni.upx2px(this.width)) {
          originX = 'left'
        } else if (y < uni.upx2px(this.height)) {
          originY = 'top'
        }
        this.origin = originX + ' ' + originY
      }
      // 检测到 极限位置 开边弹出方向
      if (this.adaption) {
        if (originY === 'top') {
          this.y = y
        } else {
          this.y = y - uni.upx2px(this.height) > 0 ? y - uni.upx2px(this.height) : 0
        }
        if (originX === 'left') {
          this.x = x
        } else {
          this.x = x - uni.upx2px(this.width) > 0 ? x - uni.upx2px(this.width) : 0
        }
      } else {
        this.x = x
        this.y = y
      }
      this.isShow = true
      // #ifndef APP-NVUE
      setTimeout(() => {
        this.notNvueAni = true
      }, 10)
      // #endif
      this.hideTarget = 'scale(0,0)'
      setTimeout(() => {
        this.animationShow()
      }, 30)
    },
    close() {
      // #ifdef APP-NVUE
      this.animationHide()
      // #endif
      // #ifndef APP-NVUE
      this.notNvueAni = false
      setTimeout(() => {
        this.isShow = false
      }, 300)
      // #endif
    },
    // 检测极限位置
    comMax() {
      let sizeArr = [this.width, this.height]
      let width = uni.upx2px(Number(sizeArr[0]))
      let height = uni.upx2px(Number(sizeArr[1]))
      this.maxX = this.winW - width
      this.maxY = this.winH - height
    },
    // nvue 打开 动画
    animationShow() {
      // #ifdef APP-PLUS-NVUE
      let tranget = ''
      if (this.type === 'zoom') {
        tranget = 'scale(1,1)'
      }
      animation.transition(this.$refs.popup, {
        styles: {
          transformOrigin: this.origin,
          transform: tranget,
          opacity: 1,
        },
        duration: 200, //ms
        timingFunction: 'ease',
      })

      if (this.$refs.mask) {
        animation.transition(this.$refs.mask, {
          styles: {
            opacity: 1,
          },
          duration: 200, //ms
          timingFunction: 'ease',
        })
      }
      // #endif
    },
    // nvue 关闭 动画
    animationHide() {
      // #ifdef APP-PLUS-NVUE
      this.$nextTick(() => {
        animation.transition(
          this.$refs.popup,
          {
            styles: {
              transform: this.type === 'zoom' ? this.hideTarget : '',
              transformOrigin: this.origin,
              opacity: 0,
            },
            duration: 200, //ms
            timingFunction: 'ease',
          },
          () => {
            this.isShow = false
          }
        )

        if (this.$refs.mask) {
          animation.transition(this.$refs.mask, {
            styles: {
              opacity: 0,
            },
            duration: 200, //ms
            timingFunction: 'ease',
          })
        }
      })
      // #endif
    },
    // 获取系统 信息
    getSystemSize() {
      this.$nextTick(() => {
        const winSize = uni.getSystemInfoSync()
        const { windowHeight, windowWidth, statusBarHeight } = winSize
        this.statusBarHeight = statusBarHeight
        this.winH = windowHeight
        this.winW = windowWidth
        // #ifdef H5
        const { windowTop } = winSize
        this.windowTop = windowTop
        // #endif
      })
    },
  },
  // 组件初始化
  created() {
    this.getSystemSize()
  },
  computed: {
    // 蒙层样式
    maskStyle() {
      return this.maskHide ? 'background-color: rgba(0, 0, 0, .4);' : ''
    },
    // 主弹窗样式
    contentStyle() {
      let width, height, x, y
      switch (this.type) {
        case 'zoom': // 当default时 样式
          width = this.width
          height = this.height
          x = this.x
          y = this.y
          let origin = this.origin
          return `left: ${x}px; top: ${y}px; width: ${width}rpx; height: ${height}rpx; transform-origin: ${origin};`
        default:
          width = this.width
          height = this.height
          x = this.x
          y = this.y
          return `left: ${x}px; top: ${y}px; width: ${width}rpx; height: ${height}rpx;`
      }
    },
  },
}
</script>

<style scoped>
.p_wrapper {
  /* position: fixed; */
  position: fixed;
  /* #ifndef APP-NVUE */
  z-index: 10000;
  /* #endif */
}

.mask {
  /* #ifndef APP-NVUE */
  z-index: 10000;
  /* #endif */
  position: fixed;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
}

.content {
  /* #ifndef APP-NVUE */
  z-index: 10001;
  /* #endif */
  position: fixed;
  border-radius: 10rpx;
}

.not_def_show {
  transform: scale(0, 0);
  opacity: 0;
}

.not_def_show_f {
  opacity: 0;
}

.not_animation_show_mask {
  transition: opacity 200;
  opacity: 1;
}

.not_animation_hide_mask {
  transition: opacity 200;
  opacity: 0;
}

/* #ifndef APP-NVUE */
.not_nvue_animation_show {
  transition: all 200ms;
  transform: scale(1, 1);
  opacity: 1;
}

.not_nvue_animation_hide {
  transition: all 200ms;
  transform: scale(0, 0);
  opacity: 0;
}

.not_nvue_animation_show_f {
  transition: all 400ms;
  opacity: 1;
}

.not_nvue_animation_hide_f {
  transition: all 400ms;
  opacity: 0;
}

/* #endif */
</style>
