<template>
	<view v-if="isShow" :style="{opacity}" id="popup-control">
		<view class="control-mark" @touchstart.prevent="closeMe" @click="closeMe" :style="{opacity}">
		</view>
		<view ref="content" class="content" :style="{top:controlData.top,left:controlData.left,right:controlData.right,opacity}">
      <template v-for="(item,index) in controlList">
        <view :key="index" class="control-item" v-if="typeof item.canDisplay == 'function' ? item.canDisplay() : item.canDisplay " @click="item.action">
        	<uni-im-icons v-if="item.icon" :code="item.icon" size="16" color="#FFF"></uni-im-icons>
        	<text class="control-item-text">{{item.title}}</text>
        </view>
      </template>
		</view>
    <view class="icon" :class="{isInTop:controlData.isInTop}" :style="{right:iconBoxRight,left:iconBoxLeft,top:controlData.top,opacity}"></view>
	</view>
  <!-- todo:多个节点都放:style="{opacity}"是为了解决nvue下，当前情况外层不能控制内层透明度的问题 -->
</template>

<script>
	import uniIm from '@/uni_modules/uni-im/sdk/index.js';
	export default {
		data(){
			return {
        controlList:[],
				isShow:false,
				controlData: {
					top:'',
          bottom:'',
					left:'unset',
					right:'unset',
					width:'',
					msg:{},
          msgContentDomInfo:{},
					isInTop:false
				},
        opacity:0
			}
		},
		computed: {
			...uniIm.mapState(['isWidescreen']),
			iconBoxLeft(){
        if(this.controlData.left != 'unset'){
          const {left:mLeft,width:mWidth} = this.controlData.msgContentDomInfo
          return mLeft + mWidth/2 + 'px'
        }else{
          return ''
        }
			},
			iconBoxRight(){
        if(this.controlData.right != 'unset'){
          const {left:mLeft,right:mRight,width:mWidth} = this.controlData.msgContentDomInfo
          const metrics = uniIm.utils.getScreenMetrics()
          return metrics.pageWidth - mRight + mWidth/2 + 'px'
        }else{
          return ''
        }
			}
		},
		mounted() {},
		methods:{
      chooseMore(){
        this.$emit('chooseMore',[this.controlData.msg])
      },
      share(e){
        // 仅支持web pc端
        if(!this.isWidescreen){
            uni.showToast({
                title:'仅支持web pc端',
                icon:'none'
            })
            return
        }
        this.$emit('share',[this.controlData.msg])
        
      },
      initControlList(msg){
        this.controlList = [
          {
            title:'复制',
            action:()=>this.copyContent(),
            canDisplay: ["userinfo-card","rich-text","text","image"].includes(msg.type) && (msg.type != 'image' || uniIm.systemInfo.uniPlatform === "web"),
          },
          {
            title:'回复',
            action:()=>this.answer(),
            canDisplay:msg._id != undefined,// 只有发送成功的消息才能回复
          },
          {
            title:'撤回',
            action:()=>this.revokeMsg(),
            canDisplay:this.canRevoke,
          },
          // {
          //   title:'删除',
          //   action:()=>this.deleteMsg(),
          //   canDisplay:msg._id != undefined, 
          // },
          {
            title:'转发',
            action:()=>this.share(),
            canDisplay:this.isWidescreen && msg._id != undefined,
          },
          {
            title:'多选',
            action:()=>this.chooseMore(),
            canDisplay:this.isWidescreen && msg._id != undefined,
          }
        ]
        
        // 拿到扩展点的数据
        let extensionsControlList = uniIm.extensions.invokeExts('msg-popup-controls',msg)
        this.controlList = this.controlList.concat(...extensionsControlList)
        
        this.controlList.map(item=>{
          const oldAction = item.action
          item.action = ()=>{
            this.isShow = false
            oldAction()
          }
        })
      },
      async show({isSelf,msg,msgContentDomInfo}){
        this.initControlList(msg)
        // 先显示出来，设置透明度为0，拿到宽度，再设置透明度为1
        this.opacity = 0
        this.controlData.msg = msg
        this.isShow = true
        await this.$nextTick()
        // #ifdef H5
        // 当蒙版弹出，鼠标右键就关闭msg-popup-control
        const popupControl = document.getElementById('popup-control')
        popupControl.addEventListener('contextmenu',(e) => {
          if(this.isShow && this.isWidescreen){
            this.isShow = false
          }
          e.preventDefault()
        })
        // #endif
        
        const controlData = {
          msgContentDomInfo,
          msg,
          isInTop: false
        }
        
        // #ifndef APP-NVUE
        const query = uni.createSelectorQuery().in(this);
        await new Promise(resolve => {
          query.selectAll('.content').boundingClientRect(data => {
            controlData.width = data[0].width + 'px'
            resolve()
          }).exec();
        })
        // #endif
        
        // #ifdef APP-NVUE
        let ref = this.$refs['content']
        await new Promise(resolve => {
          const dom = weex.requireModule('dom')
          dom.getComponentRect(ref, e => {
            controlData.width = e.size.width + 'px'
            resolve()
          })
        })
        // #endif
        
        // console.error('controlData.width',controlData.width)
        
        let metrics = uniIm.utils.getScreenMetrics()
        if (isSelf) {
          controlData.left = 'unset'
          const metrics = uniIm.utils.getScreenMetrics() 
          // console.log('msgContentDomInfo',msgContentDomInfo)
          controlData.right = metrics.pageWidth - msgContentDomInfo.right + msgContentDomInfo.width/2 - parseInt(controlData.width)/2 + 'px'
        } else {
          controlData.left = msgContentDomInfo.left + msgContentDomInfo.width / 2 - parseInt(controlData.width)/2 + 'px'
          controlData.right = 'unset'
        }
        
        controlData.isInTop = msgContentDomInfo.top > 60
        if (controlData.isInTop) {
          // #ifdef H5
          let n = -20
          // #endif
          // #ifndef H5
          let n = -65
          // #endif
          controlData.top = msgContentDomInfo.top + n + 'px'
        } else {
          // #ifdef APP
          let n = 8
          // #endif
          // #ifdef H5
          let n = 55
          // #endif
          // #ifdef MP
          let n = 10
          // #endif
          controlData.top = msgContentDomInfo.bottom + n + 'px'
        }
        
        
        if(parseInt(controlData.right) < 60){
          controlData.right = '60px'
        }
        if(parseInt(controlData.left) < msgContentDomInfo.left){
          controlData.left = msgContentDomInfo.left + 'px'
        }
        
        // console.error('dddddddta',controlData)
				this.controlData = controlData
        this.$nextTick(()=>{
          this.opacity = 1
        })
			},
			copyContent(){
				// console.log('setClipboardData');
				// console.log('this.controlData',this.controlData);
        let data = this.controlData.msg.body
        switch (this.controlData.msg.type){
          case 'userinfo-card':
            data = location.origin + '/#/?user_id='+this.controlData.msg.body.user_id
            break;
          case 'rich-text':
            data = JSON.stringify({"uni-im-rich-text-data":data})
            break;
          default:
            break;
        }

        // #ifdef H5
        if (this.controlData.msg.type === 'rich-text') {
          // 如果富文本消息是纯图片，则直接把图片内容放入剪贴板
          let [n1, n2, n3] = this.controlData.msg.body
          if (
            n1?.type === 'text' && n1?.text === '' &&
            n2?.name === 'img' && n2?.attrs?.src?.startsWith('data:image/') &&
            n3?.type === 'text' && n3?.text === ''
          ) {
            // data:image/png;base64,iVBORw0K...
            let dataurl = n2.attrs.src
            let m = /^data:(image\/.*);base64,(.*)$/.exec(dataurl)
            if (m) {
              let [_, mime, base64] = m
              let byteCharacters = atob(base64)
              let byteNumbers = new Array(byteCharacters.length)
              for (let i = 0; i < byteCharacters.length; i++) {
                byteNumbers[i] = byteCharacters.charCodeAt(i)
              }
              let byteArray = new Uint8Array(byteNumbers)
              let blob = new Blob([byteArray], { type: mime })
              let file = new File([blob], mime.replace('/', '.'), { type: mime })
              let clipboardItem = new ClipboardItem({ [mime]: file })
              navigator.clipboard.write([clipboardItem])
              uni.hideToast()
              
              return
            }
          }
        }

        if (this.controlData.msg.type === 'image') {
          let { name, url } = this.controlData.msg.body
          fetch(url).then(response => response.blob()).then(blob => {
            let mime = blob.type
            let file = new File([blob], mime.replace('/', '.'), { type: mime })
            let clipboardItem = new ClipboardItem({ [mime]: file })
            navigator.clipboard.write([clipboardItem])
          })
          uni.hideToast()
          
          return
        }
        // #endif

				uni.setClipboardData({
					data,
					complete:(e)=> {
						uni.hideToast()
						// console.log(e);
					}
				})
			},
			canRevoke() {
				let current_uid = uniCloud.getCurrentUserInfo().uid
				let {group_id,from_uid,conversation_id,create_time} = this.controlData.msg || {}
				// console.log('create_time',create_time,'group_id',group_id);
				// console.log('from_uid current_uid',this.controlData.msg,from_uid,current_uid);
        // console.log('this.controlData.msg.state',this.controlData.msg);

        //自己发的，状态 不是发送成功不能撤回 （发送成功的数据才有_id）
        if(!this.controlData.msg._id){
          return false
        }
        
        if(this.uniIDHasRole('uni-im-admin')){
          // 如果是管理员
          return true
        }
        
				let isGroupAdmin = false
				if(group_id){
					let conversation = uniIm.conversation.dataList.find(i=>i.id == conversation_id)
					isGroupAdmin = conversation.group_info.user_id == current_uid
				}
				// console.log('isGroupAdmin',isGroupAdmin);
				// 如果是群主
				if(isGroupAdmin){
					return true
				}
        
        // 以上都不是，这需要是消息的发送者，且消息创建时间小于2分钟
        return from_uid == current_uid && ( Date.now() - create_time < 1000*60*2 )
			},
			async revokeMsg(){
        // 点击后直接关闭，异步提示撤回情况
        
        
				// 再判断一遍防止，分钟在2分钟的时候右键了，然后到了第3分钟才点下的情况
				if(this.canRevoke()){
					const {conversation_id,_id:msg_id} = this.controlData.msg
          const conversation = await uniIm.conversation.get(conversation_id)
					conversation.revokeMsg(msg_id)
				}else{
					uni.showToast({
						title: '已超过2分钟，不能撤回',
						icon: 'none'
					});
				}
				// console.log('this.controlData.msg',this.controlData.msg);
			},
			async answer(){
				// console.log('answer')
				this.$emit('answer',this.controlData.msg._id)
				
			},
			async deleteMsg(){
				// #ifndef H5
				return this.other()
				// #endif
				this.controlData.msg.is_delete = true
				// 存到本地
				let conversation = await uniIm.conversation.get(this.controlData.msg.conversation_id)
				conversation.msgManager.localMsg.update(this.controlData.msg.unique_id,this.controlData.msg)
				
			},
			other(){
				uni.showToast({
					title: '暂不支持',
					icon: 'none'
				});
			},
			closeMe(evt){
				// 触摸屏忽略 click 事件
				if (uniIm.isTouchable && evt.type === 'click') return
				this.isShow = false
			}
		}
	}
</script>

<style lang="scss" scoped>
	/* #ifndef APP-NVUE */
	view {
		display: flex;
		flex-direction: column;
		box-sizing: border-box;
	}
	/* #endif */
	.content{
		background-color:#252a30;
		height: 55px;
		// width: 375rpx;
		position:fixed;
		top:0;
		border-radius: 5px;
		flex-direction: row;
		justify-content: space-around;
		align-items: center;
		/* #ifndef APP-NVUE */
		z-index: 9999;
		/* #endif */
	}
	.control-item{
		padding: 0 15px;
		justify-content: center;
		align-items: center;
	}
	.control-item-text{
		font-size: 12px;
		color:#FFFFFF;
		margin-top: 1px;
		/* #ifdef H5 */
		cursor: pointer;
		/* #endif */
	}
	/* #ifdef H5 */
	.control-item-text:hover{
		color:#c9e7ff;
	}
	/* #endif */
	.control-mark{
		position: fixed;
		top: 0;
		left: 0;
		width: 750rpx;
		flex: 1;
		height: 9000px;
		
		/* #ifndef APP-NVUE */
		width: 100vw !important;
		height: 100vh !important;
		z-index: 9999;
		/* #endif */
		
		/* #ifdef H5 */
    // 解决：通过*选择器设置了最大宽高 引起的大小撑不开的问题
		max-height:100vh !important;
		max-width:100vw !important;
		/* #endif */
		background-color: rgba(0,0,0,0.1);
	}
	
	.icon {
    position: fixed;
		transform:translate(0,-5px) rotate(45deg);
    background-color: #252a30;
    width: 10px;
    height: 10px;
    /* #ifndef APP-NVUE */
    z-index: 9999;
    /* #endif */
	}
  
  .isInTop{
  	transform:translate(0,50px) rotate(45deg);
  }
  
  /* #ifdef H5 */
  @media screen and (min-device-width:960px){
  	.control-mark {
  		background-color: rgba(255,255,255,0.05);
  	}
  }
  /* #endif */
</style>