<template>
	<view>
		<cu-custom bgColor="bg-cyan" :isBack="$squni.getPrePage() != null">
			<block slot="backText">返回</block>
			<block slot="content">AirSmartChat</block>
		</cu-custom>
		<view class="cu-chat">
			<block v-for="(x,i) in msgList" :key="i">
				<!-- 用户消息 -->
				<view v-if="x.my && x.type === 'msg'" class="cu-item self"
					:class="[i === 0 ? 'first' : '', i === 1 ? 'sec' : '']">
					<view class="main">
						<view class="content bg-cyan shadow"><!-- @click="x.msg && $squni.copy(x.msg)" -->
							<text>{{ x.msg }}</text>
						</view>
					</view>
					<image class="cu-avatar round" src="/static/logo-100.png">
						<view v-if="i === 0" class="date">{{ x.date }}</view>
				</view>
				<!-- AI消息 -->
				<view v-if="!x.my && x.type === 'msg'" class="cu-item"
					:class="[i === 0 ? 'first' : '', i === 1 ? 'sec' : '']">
					<view class="flex flex-direction align-center">
						<image class="cu-avatar round chat-avatar" src="/static/robot.png">
							<text v-if="i === 0" class="cuIcon-title" :class="[statusColor]"></text>
					</view>
					<view class="main">
						<view class="content shadow"><!-- @click="x.msg && $squni.copy(x.msg)" -->
							<img v-if="x.pic" :src="x.msg" />
							<text v-else>{{ x.msg }}</text>
						</view>
					</view>
					<view v-if="i === 0" class="date">{{ x.date }}</view>
				</view>
				<view v-if="x.type === 'error'" class="cu-info">
					<text class="cuIcon-roundclosefill text-red "></text> {{ x.msg }}
				</view>
			</block>

			<view v-if="msgLoading" class="cu-item">
				<view class="flex flex-direction align-center">
					<image class="cu-avatar round chat-avatar" src="/static/robot.png">
				</view>
				<view class="main">
					<text class="cuIcon-loading2 cuIconfont-spin text-cyan"></text>
				</view>
			</view>
		</view>

		<view class="cu-bar foot input" :style="[{bottom:inputBottom+'px'}]">
			<view class="tip-box">
				<button class="cu-btn round shadow sm cuIcon line-cyan" @click="startNewChat">
					<text class="cuIcon-paint"></text>
				</button>
				<button class="cu-btn round shadow sm line-cyan"
					@click="$squni.navigateTo('/pages/main/history')">历史消息</button>
				<button class="cu-btn round shadow sm bg-orange"
					@click="$squni.navigateTo('/pages/main/prompt/prompt')">提示词</button>
				<button class="cu-btn round shadow sm line-cyan" @click="openBottomFunc">我的信息</button>
			</view>
			<!-- <view class="action func" @click="openBottomFunc">
				<text class="cuIcon-list text-cyan" style="font-size: 60upx;"></text>
			</view> -->
			<view class="input-msg">
				<ol class="tip-list">
					<li class="tip-item" v-for="item in inputTipList" :key="item.type" @click="handleSendMsg(item)">
						{{ item.name }}
					</li>
				</ol>
				<input v-model="msg" class="solid padding-lr" :adjust-position="false" :focus="false" maxlength="5000"
					cursor-spacing="10" :placeholder="loading ? '小AirSmart正在思考中，请稍后~' : '你可以问我任何问题或输入  “/”  获取模板'" @focus="inputFocus"
					@blur="inputBlur" @confirm="sendMsg" @input="handleInput"></input>
			</view>
			<!-- <view class="action">
				<text class="cuIcon-emojifill text-grey"></text>
			</view> -->
			<button class="cu-btn bg-cyan shadow" :disabled="loading" @click="sendMsg">
				<text class="cuIcon-loading2 cuIconfont-spin"
					v-if="loading || !ready"></text>{{ !ready ? '连接中' : '发送' }}
			</button>
		</view>

		<bottom-func v-if="bottomFuncShow" ref="bottomFunc" :chatAsset="chatAsset"
			@rewarded-video-ad="() => chatAsset.dfn += 2"></bottom-func>
	</view>
</template>

<script>
	import {
		dateFormat,
		interval
	} from '@/util/squ.js'
	import squni, {
		scrollToBottom
	} from '@/util/squni.js'
	import websocket from '@/util/websocket'
	import {
		sendMsgApi,
		getUserChatAssetApi,
		startNewChatApi,
		findPromptListApi,
		msgList,
		sendMsgPic
	} from '@/api/chat.js'
	import BottomFunc from './bottom-func'
	const HELLO_MSG = {
		type: 'msg',
		my: false,
		msg: '连接中，请稍后~',
		date: dateFormat(new Date(), 'yyyy年MM月dd日 hh:mm')
	}
	export default {
		components: {
			BottomFunc
		},
		data() {
			return {
				loading: false,
				userId: null,
				msgList: [HELLO_MSG],
				msgContent: "",
				msg: "",
				msgType: 0,
				inputBottom: 0,
				bottomFuncShow: false,
				chatAsset: {},
				assetType: 'n',
				statusColor: 'text-red',
				statusTimer: null,
				msgLoading: false,
				promptId: null,
				curPrompt: {},
				inputTipList: []
			}
		},
		computed: {
			ready() {
				return this.statusColor === 'text-green'
			}
		},
		watch: {
			loading(n, o) {
				if (n !== o && !n) {
					let last = this.msgList[this.msgList.length - 1]
					if (!last.my) {
						this.addHistory(last)
					}
				}
			},
			statusColor(n, o) {
				if (n === 'text-green') {
					let prompt = ''
					if (this.curPrompt && this.curPrompt.title) {
						prompt = `（提示词：${this.curPrompt.title}）`
					}
					HELLO_MSG.msg = '你好，我是AirSmartChat机器人，可以帮你解答疑惑或提供灵感' + prompt
				} else {
					HELLO_MSG.msg = '连接中，请稍后~'
				}
			}
		},
		async onShow() {
			await this.$ready

			this.userId = this.$store.getters.userId
			if (!this.userId) {
				this.$squni.toast('请先进行登录哦')
				return
			}

			this.promptId = this.$squni.getCurQuery('promptId')
			if (this.promptId) {
				findPromptListApi({
					id: this.promptId
				}).then(res => {
					if (res.status === 'success') {
						this.curPrompt = res.data

						if (this.ready && HELLO_MSG.msg.indexOf('提示词') < 0) {
							let prompt = ''
							if (this.curPrompt && this.curPrompt.title) {
								prompt = `（提示词：${this.curPrompt.title}）`
							}
							HELLO_MSG.msg += prompt
						}
					}
				})
			}

			getUserChatAssetApi().then(res => {
				if (res.status === 'success') {
					this.chatAsset = res.data
				}
			})

			this.heartStatus()
			try {
				//建立socket连接
				websocket.connectSocket(this.$config.wssUrl + '/tools/chat/user/' + this.userId, msg => {
					this.recvMsg(msg)
				}, () => {
					//如果连接成功则发送心跳检测
					this.heartBeatTest()
				})
			} catch (error) {
				console.log('websocket connectSocket error:' + error)
			}
		},
		onHide() {
			this.closeSocket()
		},
		methods: {
			logout() {
				this.loginLoading = true
				doLoginApi('H5', {
					username: this.email || this.phone || this.username,
					password: this.password
				}).then(res => {
					this.loginLoading = false
					if (res === LoginSuccess) {
						uni.showToast({
							title: '登录成功'
						})
						// 跳转到主页发现已经登录，会自动重新获取用户信息，此处无需获取
						window.location.href = getUrlQuery('_originHref')
					} else {
						uni.showToast({
							title: (res && res.data && res.data.message) || '登录失败',
							icon: 'none'
						})
						this.createCode(4)
					}
				})
			},
			sendMsg() {
				if (this.msg == "") {
					this.$squni.toast('请先输入您的问题哦')
					return
				}
				let msg = this.msg
				this.putMsg(this.msg, true)
				this.msgLoading = true
				this.loading = true
				
				// ======== 开发环境模拟回复 ========
				// return this.mockReply()
				// ======== 开发环境模拟回复 ========
				
				if (this.calcAsset() === false) {
					this.loading = false
					return
				}
				
				if(this.msgType === 2){
					sendMsgPic({
						userId: this.$squni.getStorageSync('userId'),
						question: msg,
						type: this.msgType
					}).then(res => {
						if(res.code === 20000) {
							JSON.parse(res.data.ack).map(i => {
								this.putMsg(i.url, false, 'msg', true)
								this.loading = false
								this.msgLoading = false
								this.msgType = 0
							})
						}else{
							this.putMsgError('机器人被拔网线了，请稍后再试~')
						}
					})
				}else{
					// 发送消息: M1/M2
					websocket.sendMessage(JSON.stringify({
						model: 'M1',
						msg: msg,
						platform: this.$squni.getStorageSync('platform'),
						openid: this.$squni.getStorageSync('openid'),
						promptId: this.promptId
					}), null, () => {
						this.putMsgError('机器人被拔网线了，请稍后再试~')
					})
				}
			},
			recvMsg(msg) {
				this.msgLoading = false
				if (!msg) {
					this.putMsgError('机器人开小差了，请稍后再试~')
					return
				}
				// 发送消息
				// 1+1
				// 收到消息
				// {"role":"assistant","content":null}
				// {"role":null,"content":"2"}
				// {"role":null,"content":null}
				// [DONE]
				if (msg === '[DONE]') {
					this.loading = false
				} else {
					try {
						let msgJson = JSON.parse(msg)
						if (msgJson.role === 'sqchat') {
							let content = msgJson.content
							if (msgJson.codeKey) {
								content += `[${msgJson.codeKey}]`
								if (msgJson.codeKey === 'chat.asset_short') {
									this.openBottomFunc()
								} else if (msgJson.codeKey.indexOf('chat.asset_') >= 0) {
									this.chatAsset[this.assetType]++
								}
							}
							this.putMsgError(content)
						}
						if (msgJson.role === 'assistant') {
							this.putMsg('', false)
						} else if (msgJson.role == null && msgJson.content) {
							this.msgList[this.msgList.length - 1].msg += msgJson.content
							scrollToBottom()
						}
					} catch (error) {
						this.putMsgError(msg)
					}
				}
			},
			startNewChat() {
				HELLO_MSG.date = dateFormat(new Date(), 'yyyy年MM月dd日 hh:mm')
				this.msgList = [HELLO_MSG]
				startNewChatApi()
			},
			// sendMsgBak() {
			// 	let that = this
			// 	if (this.msg == "") {
			// 		return
			// 	}
			// 	this.msgContent += (this.userId + ":" + this.msg + "\n")
			// 	this.putMsg(this.msg, true)
			// 	this.loading = true

			// 	// ======== 开发环境模拟回复 ========
			// 	return this.mockReply()
			// 	// ======== 开发环境模拟回复 ========

			// 	sendMsgApi({
			// 		userId: this.userId + '',
			// 		question: this.msgContent
			// 	}).then(({
			// 		status,
			// 		data
			// 	}) => {
			// 		if (status === 'success') {
			// 			this.putMsg(data.ack, false)
			// 			this.msgContent += ("openai:" + this.msg + "\n")
			// 		} else {
			// 			this.putMsg(res.message || '机器人开小差了，请稍后再试~', false, 'error')
			// 		}
			// 		that.loading = false
			// 	})
			// },
			calcAsset() {
				if (this.chatAsset.dfn > 0) {
					this.chatAsset.dfn--
					this.assetType = 'dfn'
				} else if (this.chatAsset.n > 0) {
					this.chatAsset.n--
					this.assetType = 'n'
				} else {
					this.$squni.toast('剩余次数不足')
					this.openBottomFunc()
					return false
				}
			},
			putMsg(msg, my = false, type = 'msg', pic = false) {
				let item = {
					type: type,
					msg: msg,
					my: my,
					pic: pic,
					date: dateFormat(new Date(), 'yyyy年MM月dd日 hh:mm')
				}
				this.msgList.push(item)
				scrollToBottom()
				if (my) {
					this.addHistory(item)
					// 清除消息
					this.msg = ''
					this.msgReply = ''
				}
			},
			putMsgError(msg) {
				this.putMsg(msg, false, 'error')
				this.msgLoading = false
				this.loading = false
			},
			addHistory(item) {
				if (item.type === 'msg') {
					let chatHistory = this.$squni.getStorageSync('chatHistory')
					if (!chatHistory) {
						chatHistory = []
					}
					if (chatHistory.length >= 50) {
						chatHistory.splice(0, 1)
					}
					chatHistory.push(item)
					this.$squni.setStorageSync('chatHistory', chatHistory)
				}
			},
			//心跳检测
			heartBeatTest() {
				let globalTimer = null
				//清除定时器
				clearInterval(globalTimer)
				//开启定时器定时检测心跳
				globalTimer = setInterval(() => {
					//发送消息给服务端
					websocket.sendMessage('PING', null, () => {
						//如果失败则清除定时器
						clearInterval(globalTimer)
					})
				}, 10000)
			},
			heartStatus() {
				this.statusTimer = interval(() => {
					if (websocket.isOpen) {
						this.statusColor = 'text-green'
					} else if (this.statusColor === 'text-red') {
						this.statusColor = 'text-yellow'
					} else {
						this.statusColor = 'text-red'
					}
				}, this.statusTimer, 200)
			},
			closeSocket() {
				websocket.closeSocket()
				clearInterval(this.statusTimer)
				this.statusColor = 'text-red'
			},
			inputFocus(e) {
				this.inputBottom = e.detail.height
			},
			inputBlur(e) {
				this.inputBottom = 0
			},
			// 对话输入框输入'/'显示提示信息
			handleInput(e) {
				if (e.detail.value.startsWith('/')) {
					msgList().then(res => {
						this.inputTipList = res.data
					})
				}
			},
			handleSendMsg(e){
				this.msgType = e.type
				this.msg = e.name
				this.inputTipList = []
			},
			openBottomFunc() {
				this.bottomFuncShow = true
				this.$nextTick(() => {
					this.$refs.bottomFunc.open()
				})
			},
			mockReply() {
				// 开发环境模拟回复
				if (process.env.NODE_ENV === 'development') {
					setTimeout(() => {
						this.putMsg('这是模拟返回消息: ' + new Date(), false)
						this.loading = false
					}, 1000)
					return
				}
			}
		}
	}
</script>

<style>
	page {
		padding-bottom: 220upx;
	}

	.cu-chat .chat-avatar.cu-avatar {
		width: 82upx;
		height: 82upx;
	}

	.cu-item:not(.first) {
		padding-bottom: 0upx;
	}

	.cu-item.sec {
		padding-top: 0upx;
	}

	.cu-chat .cu-item>.main {
		max-width: calc(100% - 160upx);
	}

	.main .content {
		word-wrap: break-word;
		cursor: text;
		user-select: text;
	}

	.cu-bar.foot {
		box-shadow: 0 -0.5px 1px rgba(0, 0, 0, 0.1);
		align-items: flex-end;
	}

	.foot {
		padding-top: 20upx;
		padding-bottom: 60upx;
	}

	.foot .cu-btn {
		margin-right: 20upx;
		width: 200upx;
	}

	.foot .action.func {
		margin-left: 30upx;
	}

	.foot .tip-box {
		position: absolute;
		top: -60upx;
		margin: 0 30upx;
	}
	
	.input-msg{
		width: 100%;
		.tip-list{
			margin: 0 40upx;
			padding: 0 40upx;
			
			.tip-item{
				cursor: pointer;
				color: #909399;
				line-height: 64upx;
			}
			
			.tip-item:hover{
				background: #d9ecff;
				color: #000;
			}
		}
	}
</style>