<template>
	<view class="main">
		<view class="content">
			<scroll-view scroll-y="true" class="scroll-view" :scroll-into-view="poaMessgae">
				<view class="list-scroll-view">
					<view class="block" v-for="(item,index) in list" :key="index">
						<view class="time" v-if="index == 0 || item.time - list[index-1].time >= 300000">
							<text>{{formatDate(item.time)}}</text>
						</view>
						<view class="list" :id="item.speaker._id != userId ? 'left' : 'right'">
							<image class="avatar"
								:src="item.speaker&&item.speaker.icon.length>0?item.speaker.icon[0].url:config.user_url[0].url"
								mode=""></image>
							<text class="record" v-if="item.type == 'text'">{{item.content}}</text>
							<image :src="item.content" v-if="item.type == 'image'" @tap="onPreview(item.content)"
								mode="widthFix">
							</image>
							<view class="record" v-if="item.type == 'record'" @tap="onPlay(item.content,index)">
								<uni-icons v-if="item.speaker._id != userId" custom-prefix="iconfont"
									type="icon-zuobofang" size="15" color="#333333">
								</uni-icons>
								<text class="voice">{{item.voice}}</text>"
								<uni-icons v-if="item.speaker._id == userId" custom-prefix="iconfont"
									type="icon-youbofang" size="15" color="#ffffff">
								</uni-icons>
							</view>
						</view>
					</view>
					<view id="poaMessgae"></view> <!-- 仅用于定位到消息最后一条 -->
				</view>
			</scroll-view>
		</view>
		<view class="bottom">
			<submit_1 :record="record" :inrecord="inrecord" :isRecorder="isRecorder" @toSend="toSend" @heights="heights"
				@onRecorderchange="onRecorderchange" @onStart="onStart" @onEnd="onEnd"></submit_1>
		</view>
		<!-- 语音 -->
		<uni-popup ref="voice" background-color="#fff">
			<view class="image">
				<image class="avatar" :src="config.audio_url[0].url"></image>
			</view>
		</uni-popup>
	</view>
</template>

<script>
	import WebSocket from "@/common/websocket.js"
	import submit_1 from './common/submit_1.vue';
	export default {
		components: {
			submit_1,
		},
		data() {
			return {
				id: '',
				// 群
				groupId: '',
				// 病人
				patientId: '',
				// 医生
				doctorId: '',
				// 用户id
				userId: '',
				user: {},
				config: {},
				// 聊天列表数据
				list: [],
				total: 0,
				skip: 0,
				limit: 20,
				record: '', // 全局唯一录音管理区
				inrecord: false, // 是否处于录音状态
				isRecorder: false, // 是否处于语音状态
				bgAudioManager: '', // 全局音频播放
				poaMessgae: 'poaMessgae', //滚动到最底部
				client: '' //实时通信
			}
		},
		onLoad: async function(e) {
			const that = this;
			that.$set(that, `groupId`, e && e.groupId || '');
			that.$set(that, `patientId`, e && e.patientId || '');
			that.$set(that, `doctorId`, e && e.doctorId || '');
			uni.setNavigationBarTitle({
				title: e && e.title || '聊天室'
			});
			// 全局唯一录音管理器
			that.record = uni.getRecorderManager();
			await that.searchToken();
			await that.searchConfig();
			await that.search();
			// 滚动到最底部
			that.poalast()
			// stomp协议请求 实时链接
			that.initWS()
		},
		// 离开页面是关闭连接 
		// 我的业务是仿微信这种，每次连接人不同，频繁建立新连接，根据自己需要决定什么时候关闭连接
		onUnload() {
			const that = this;
			that.client && that.client.close()
		},
		methods: {
			// 用户信息
			searchToken() {
				const that = this;
				try {
					const res = uni.getStorageSync('token');
					if (res) {
						const user = that.$jwt(res);
						that.$set(that, `user`, user);
						if (user.role == 'Nurse') that.$set(that, `userId`, user.doctor);
						else that.$set(that, `userId`, user._id);
					}
				} catch (e) {}
			},
			searchConfig() {
				const that = this;
				try {
					const res = uni.getStorageSync('config');
					if (res) that.$set(that, `config`, res);
				} catch (e) {}
			},
			async search() {
				const that = this;
				// 聊天记录
				let info = {
					skip: that.skip,
					limit: that.limit,
					patient: that.patientId,
					group: that.groupId,
					doctor: that.doctorId
				}
				const arr = await that.$api(`/chat`, 'GET', {
					...info
				})
				if (arr.errcode == '0') {
					that.$set(that, `list`, arr.data)
				} else {
					uni.showToast({
						title: arr.errmsg,
						icon: 'none'
					});
				}
			},
			// 处理时间
			formatDate(value) {
				if (typeof(value) == 'undefined') {
					return ''
				} else {
					let date = new Date(value)
					let now = new Date()
					let y = date.getFullYear()
					let MM = date.getMonth() + 1
					MM = MM < 10 ? ('0' + MM) : MM
					let d = date.getDate()
					d = d < 10 ? ('0' + d) : d
					let h = date.getHours()
					h = h < 10 ? ('0' + h) : h
					let m = date.getMinutes()
					m = m < 10 ? ('0' + m) : m
					let s = date.getSeconds()
					s = s < 10 ? ('0' + s) : s
					if (now.getDate() - d == 1 && now - date < 172800000) {
						return '昨天' + h + ':' + m
					} else if (now - date < 86400000) {
						return h + ':' + m
					} else if (now - date >= 86400000 && now - date < 31536000000) {
						return MM + '-' + d + ' ' + h + ':' + m
					} else if (now - date >= 31536000000) {
						return y + '-' + MM + '-' + d + ' ' + h + ':' + m
					}
				}
			},
			//输入框高度
			heights(e) {
				const that = this;
				that.poalast()
			},
			// 切换语音 or 键盘
			onRecorderchange() {
				const that = this
				if (that.isRecorder) {
					that.isRecorder = false
				} else {
					uni.authorize({
						scope: 'scope.record',
						success: res => {
							that.isRecorder = true
						}
					})
				}
			},
			// 长按开始录入语音
			onStart() {
				const that = this
				that.$set(that, `inrecord`, true);
				that.$refs.voice.open('center')
				that.record.start({
					format: "mp3"
				})
			},
			// 长按结束录入语音
			onEnd() {
				const that = this
				const fileUrl = that.$config.serverUrl;
				that.$set(that, `inrecord`, false);
				that.$refs.voice.close('center')
				that.record.stop()
				// 监听录音暂停的回调参数
				that.record.onStop(res => {
					if (res.duration < 1000) {
						return that.global.toast('请说话久一点')
					}
					// 上传音频
					uni.uploadFile({
						url: `${fileUrl}/visit/api/files/chat_voice/${that.user._id}/upload`,
						filePath: res.tempFilePath,
						name: `file`,
						formData: {},
						success: (arr) => {
							const file = JSON.parse(arr.data)
							let mess = {
								type: 'record',
								voice: Math.round(res.duration / 1000), // 时长
								content: fileUrl + file.data.uri,
								time: new Date() - 0
							}
							// 写在上传回调内
							that.toSend(mess)
						},
						fail: (err) => {
							console.log('uploadImage fail', err);
						},
					});
					let mess = {
						type: 'record',
						voice: Math.round(res.duration / 1000), // 时长
						content: res.tempFilePath,
						time: new Date() - 0
					}
					// 写在上传回调内
					that.toSend(mess)
				})
				that.record.onError(err => {
					that.global.toast('获取录音失败')
				})
			},
			// 播放音频
			onPlay(e, index) {
				const that = this
				that.bgAudioManager = uni.createInnerAudioContext()
				that.bgAudioManager.src = e
				that.bgAudioManager.play()
				that.bgAudioManager.onEnded(() => {
					that.bgAudioManager.offPlay()
					that.bgAudioManager.offEnded()
					that.bgAudioManager = null
				})
			},
			// 预览图片
			onPreview(e) {
				uni.previewImage({
					urls: [e]
				})
			},
			// 消息链接
			initWS() {
				const that = this
				const brokerURL = that.$config.brokerURL;
				WebSocket.init(
					`${brokerURL}`,
					// 传参
					{
						host: 'visit',
						login: 'visit',
						passcode: 'visit'
					},
					// ws断开回调
					() => {
						that.initWS()
					}
				).then((client) => {
					that.client = client
					// 订阅
					that.subscription = client.subscribe(
						// 路径
						`/exchange/chatEx/${that.groupId}_${that.patientId}`,
						// 接收到的数据
						(res) => {
							console.log(res);
							that.list.push(JSON.parse(res.body))
							// 滚动到最底部
							that.poalast()
						},
					)
				})
			},
			// 发送消息
			async toSend(e) {
				const that = this;
				const mess = {
					speaker: that.user._id,
					speaker_type: that.user.role,
					group: that.groupId,
					patient: that.patientId,
					doctor: that.doctorId,
				}
				const data = {
					...e,
					...mess
				}
				let res = await that.$api(`/chat`, 'POST', data)
				if (res.errcode == '0') {
					that.search()
					that.$set(that, `isRecorder`, false);
					that.poalast() // 定位消息最后一行
				} else {
					uni.showToast({
						title: res.errmsg,
						icon: 'none'
					});
				}
			},
			// 定位到消息最后一行
			poalast() {
				const that = this
				that.$nextTick(() => {
					that.$set(that, `poaMessgae`, '');
					setTimeout(() => {
						that.$set(that, `poaMessgae`, 'poaMessgae');
					}, 50)
				})
			},
		}
	}
</script>

<style scoped lang="scss">
	.main {
		display: flex;
		flex-direction: column;
		box-sizing: border-box;
		width: 100vw;
		height: 100vh;

		.content {
			position: relative;
			flex-grow: 1;

			.time {
				display: flex;
				align-items: center;
				flex-direction: column;
				margin: 2vw 0;

				text {
					background: rgba(0, 0, 0, 0.6);
					color: var(--f6Color);
					padding: 1vw 2vw;
					border-radius: 5px;
					font-size: var(--font12Size);
				}
			}

			.list {
				display: flex;
				align-items: flex-start;
				margin-bottom: 4vw;

				.avatar {
					border-radius: 50%;
					width: 10vw;
					height: 10vw;
				}

				image {
					width: 20vw;
				}

				text {
					font-size: var(--font14Size);
					font-family: PingFang SC-Regular, PingFang SC;
					font-weight: 400;
					max-width: 70vw;
				}

				.record {
					display: flex;
					align-items: center;
					word-break: break-all;

					.voice {
						margin: 0 1vw;
					}
				}
			}

			#left {
				.avatar {
					margin-right: 2vw;
				}

				.record {
					background: #F4F8FB;
					border-radius: 0rpx 2vw 2vw 2vw;
					padding: 2vw 3vw;
					color: var(--f33Color);
				}
			}

			#right {
				flex-direction: row-reverse;

				.avatar {
					margin-left: 2vw;
				}

				.record {
					background: #6B72F6;
					border-radius: 2vw 0 2vw 2vw;
					padding: 2vw 3vw;
					color: var(--mainColor);
				}
			}
		}

		.bottom {
			background: var(--mainColor);
		}
	}

	.image {
		display: flex;
		align-items: center;

		.avatar {
			width: 50vw;
			height: 50vw;
		}
	}

	.scroll-view {
		position: absolute;
		top: 0;
		left: 0;
		right: 0;
		bottom: 0;

		.list-scroll-view {
			display: flex;
			flex-direction: column;
			margin: 0 2vw;
		}
	}
</style>