<template>
	<view class="chat flex-col">
		<view class="content" @tap="showEmoji = false">
			<scroll-view style="height: 100%;" :scroll-y="true" :scroll-top="scrollTop" :scroll-into-view="intoView" @scrolltoupper="scrollToupper">
				<view class="loading flex row-center" v-if="pageStatus == 'loading'"><u-loading mode="flower" size="40"></u-loading></view>
				<view class="chat-lists">
					<view
						class="chat-item"
						v-for="(item, index) in recoreds"
						:id="`chat-item_${item.id}`"
						:key="item.id"
						:class="{
							right: item.from_type == 'user',
							left: item.from_type == 'kefu',
							visibility: showIndex > index
						}"
					>
						<!-- 普通聊天记录 -->
						<template v-if="item.type == 1">
							<!-- 时间 -->
							<view class="text-center m-b-30 white" v-if="timeFormat(item, index)">
								<view class="chat-tips xs">{{ timeFormat(item, index) }}</view>
							</view>
							<view class="chat-info">
								<image class="avatar" :src="$getImageUri(item.from_avatar)"></image>
								<!-- 文本 -->
								<view class="text-box" v-if="item.msg_type == 1"><rich-text :nodes="replaceEmoji(item.msg)" space="nbsp"></rich-text></view>
								<!-- 图片 -->
								<view class="image-box" v-if="item.msg_type == 2">
									<image class="image" mode="widthFix" :src="$getImageUri(item.msg)" @tap="previewImage($getImageUri(item.msg))"></image>
								</view>
								<!-- 商品 -->
								<view class="goods m-r-20 goods-box" v-if="item.msg_type == 3">
									<view class="goods-img m-r-20"><image style="width: 140rpx;height: 140rpx;" :src="$getImageUri(item.goods.image)"></image></view>
									<view class="goods-info flex-1">
										<view class="line-2">{{ item.goods.name }}</view>
										<view class="flex m-t-10 row-between">
											<price-format
												:color="colorConfig.primary"
												:subscript-size="26"
												:first-size="38"
												:second-size="26"
												:price="item.goods.min_price"
											></price-format>
										</view>
									</view>
								</view>
							</view>
						</template>
						<!-- 通知类型记录 -->
						<template v-else>
							<view class="text-center white">
								<view class="muted xs">{{ item.msg }}</view>
							</view>
						</template>
					</view>
				</view>
				<view class="error" v-if="isError">
					<view class="error-msg text-center xs">{{ errorMsg }}</view>
				</view>
				<view id="bottom"></view>
			</scroll-view>
		</view>

		<view class="footer" @tap="showGoods = false">
			<view class="footer-input flex">
				<view class="album" @tap="uploadFile"><image class="icon" src="@/static/images/icon_album.png"></image></view>
				<view class="input-contain flex">
					<input v-model="msg" class="text-area" confirm-type="send" maxlength="-1" @focus="scrollToBottom" @confirm="sendText" />
					<image class="icon" src="@/static/images/icon_emoji.png" @tap="handleEmojiShow"></image>
				</view>
				<button size="sm" class="send-btn" @tap="sendText">发送</button>
			</view>
			<view class="emoji-wrap" :class="{ 'emoji-show': showEmoji }">
				<scroll-view style="height:100%;" scroll-y="true"><emoji @input="handleEmojiInput"></emoji></scroll-view>
			</view>
		</view>

		<view class="goods" v-if="showGoods">
			<view class="close" @tap="showGoods = false"><u-icon name="close-circle-fill" color="#ccc" size="40"></u-icon></view>
			<view class="goods-img m-r-20"><u-image width="140rpx" height="140rpx" :src="goodsInfo.image"></u-image></view>
			<view class="goods-info flex-1">
				<view class="line-2">{{ goodsInfo.name }}</view>
				<view class="flex m-t-10 row-between">
					<price-format :color="colorConfig.primary" :subscript-size="26" :first-size="38" :second-size="26" :price="goodsInfo.min_price"></price-format>
					<view class="send-btn" @tap="sendGoods">发送链接</view>
				</view>
			</view>
		</view>
	</view>
</template>

<script>
import Socket from '@/utils/socket';
import { chatRecord } from '@/api/user';
import { getChatConfig } from '@/api/app';
import { getGoodsDetail } from '@/api/store';
import { client, uploadFile, getRect, debounce } from '@/utils/tools';
import { timeFormatChat } from '@/utils/date';
import { mapMutations } from 'vuex';
export default {
	data() {
		return {
			pageStatus: 'loading',
			scrollTop: '',
			intoView: '',
			page: 1,
			msg: '',
			socket: {},
			kefu: {},
			showEmoji: false,
			recoreds: [],
			errorMsg: '',
			goodsInfo: {},
			isError: false,
			showGoods: false,
			showIndex: -1
		};
	},
	computed: {
		// 设置记录
		timeFormat() {
			return (item, index) => {
				let timeFmt = timeFormatChat(item.create_time_stamp);
				if (index && item.create_time_stamp - this.recoreds[index - 1].create_time_stamp < 300 && !item.show_time) {
					timeFmt = '';
				}

				return timeFmt;
			};
		},
		// 表情转换
		replaceEmoji() {
			return str => str.replace(/\[em-([a-z_]+)\]/g, `<span class="em em-$1"></span>`);
		},
		// 获取图片域名
		$getImageUri() {
			return url => this.$store.state.app.config.base_domain + url;
		}
	},
	watch: {
		kefu(val) {
			if (val.id) {
				this.setTitle(val.nickname);
			}
		}
	},
	methods: {
		// 初始化
		init() {
			this.shopId = this.$Route.query.shop_id || 0;
			this.goodsId = this.$Route.query.goods_id;
			this.socket = new Socket(this.appConfig.ws_domain, {
				token: this.$store.getters.token,
				type: 'user',
				client,
				shop_id: this.shopId
			});
			this.socket.addEvent('connect', () => {
				this.setTitle('连接中...');
			});
			this.socket.addEvent('open', () => {
				this.setTitle(this.kefu.nickname);
				this.isError = false;
			});
			this.socket.addEvent('message', data => {
				switch (data.event) {
					case 'login':
						this.loginEvent(data.data);
						break;
					case 'chat':
						this.chatEvent(data.data);
						break;
					case 'transfer':
						this.transferEvent(data.data);
						break;
					case 'error':
						this.errorEvent(data.data);
						break;
				}
			});
			this.socket.addEvent('error', data => {
				this.setTitle('连接失败');
			});
		},

		showTips(msg) {
			if (!msg) {
				console.log('1111');
				// uni.navigateTo({
				// 	url: '/bundle/pages/contact_offical/contact_offical?id=' + this.shopId,
				// 	success(e) {
				// 		console.log(e, 'cg');
				// 	},
				// 	fail(e) {
				// 		console.log(e, 'sb');
				// 	}
				// });
				// #ifdef APP
				setTimeout(function() {
					uni.redirectTo({
						url: `/bundle/pages/contact_offical/contact_offical?id=${this.shopId}`
					});
				}, 2000);
				// #endif
				// #ifdef H5
				uni.redirectTo({
					url: `/bundle/pages/contact_offical/contact_offical?id=${this.shopId}`
				});
				// #endif
				return;
			} else {
				uni.showModal({
					title: '温馨提示',
					content: msg,
					success: res => {
						if (res.confirm) {
							uni.redirectTo({
								url: `/bundle/pages/contact_offical/contact_offical?id=${this.shopId}`
							});
						} else if (res.cancel) {
							this.$Router.back();
						}
					}
				});
			}
		},
		getConfig() {
			return getChatConfig({
				shop_id: this.shopId
			})
				.then(res => {
					return Promise.resolve(res);
				})
				.catch(() => {
					return Promise.reject();
				});
		},
		// 获取数据
		async getData() {
			try {
				const res = await this.getConfig();
				console.log(res);
				if (res.code == 0) return this.showTips(res.msg);
				await this.getChatRecord();
				this.getGoods();
				this.scrollToBottom();
				if (!this.kefu.id) {
					this.setTitle('客服不在线');
					return;
				}
				this.socket.connect();
			} catch (e) {}
		},
		getGoods() {
			if (!this.goodsId) return;
			getGoodsDetail({
				goods_id: this.goodsId
			}).then(res => {
				if (res.code == 1) {
					this.goodsInfo = res.data;
					if (this.kefu.id) {
						this.showGoods = true;
					}
				}
			});
		},
		// 图片预览
		previewImage(url) {
			uni.previewImage({
				urls: [url]
			});
		},

		// 上传图片
		async uploadFile() {
			const [error, success] = await uni.chooseImage({
				count: 1
			});
			if (error) {
				return;
			}
			uni.showLoading({
				title: '上传中...'
			});
			try {
				const file = await uploadFile(success.tempFilePaths[0]);
				this.send(file.base_uri, 2);
				uni.hideLoading();
			} catch (e) {
				this.$toast({
					title: '上传失败，请稍后再试'
				});
				uni.hideLoading();
			}
		},
		// 发送文本
		sendText() {
			if (!this.msg) return;
			this.send(this.msg, 1);
			this.msg = '';
		},
		// 发送商品
		sendGoods() {
			this.showGoods = false;
			this.send(this.goodsId, 3);
		},

		// 获取聊天记录
		async getChatRecord() {
			const { page, pageStatus } = this;
			if (pageStatus == 'finish') return;
			const res = await chatRecord({
				shop_id: this.shopId,
				page_no: page
			});
			if (res.code == 1) {
				let toid = 0;
				this.page++;
				const { kefu, record } = res.data;
				this.kefu = kefu;
				this.showIndex = record.list.length;
				if (this.recoreds.length) {
					toid = this.recoreds[0].id;
					this.recoreds[0].show_time = true;
				}

				this.recoreds.unshift(...record.list);
				this.$nextTick(() => {
					if (!record.more) {
						this.pageStatus = 'finish';
					}
					this.scrollToItem(toid);
					this.showIndex = -1;
				});
			}
		},
		// 发送消息
		send(msg, type) {
			this.socket.send({
				event: 'chat',
				data: {
					msg,
					msg_type: type, // 暂定 1=>文本；2=>图片；3=>表情
					to_id: this.kefu.id, // 接收人id；客服发给用户则为user_id, 用户发给客服则为kefu_id
					to_type: 'kefu'
				}
			});
		},
		// 显示、隐藏表情库
		handleEmojiShow() {
			this.showEmoji = !this.showEmoji;
			if (!this.showEmoji) return;
			setTimeout(() => {
				this.scrollToBottom();
			}, 300);
		},
		scrollToupper() {
			this.getChatRecord();
		},
		scrollToBottom() {
			this.intoView = 'bottom';
			this.$nextTick(() => {
				this.intoView = '';
			});
		},
		scrollToItem(id) {
			this.intoView = `chat-item_${id}`;
			this.$nextTick(() => {
				this.intoView = '';
			});
		},

		handleEmojiInput(val) {
			this.msg = this.msg + val;
		},
		chatEvent(data) {
			this.isError = false;
			if (data.from_type == 'kefu') {
				uni.vibrateLong({
					success: function() {
						console.log('success');
					}
				});
			}
			if (data.shop_id != this.shopId) {
				return;
			}
			this.recoreds.push(data);
			this.$nextTick(() => {
				getRect('#bottom').then(res => {
					if (res.bottom < 1000) {
						this.scrollToItem(data.id);
					}
				});
			});
		},
		errorEvent(data) {
			this.errorMsg = data.msg;
			this.isError = true;
			this.$nextTick(() => {
				this.scrollToBottom();
			});
		},
		loginEvent(data) {
			// 登录成功，发送用户上线通知
			this.socket.send({
				event: 'user_online',
				data: {
					kefu_id: this.kefu.id
				}
			});
		},
		transferEvent(data) {
			this.kefu = data;
		},
		setTitle(title) {
			uni.setNavigationBarTitle({
				title
			});
		}
	},
	async onLoad() {
		this.scrollToupper = debounce(this.scrollToupper, 500, this);
		this.init();
		this.getData();
	},
	onUnload() {
		this.socket.close();
	},
	onReady() {}
};
</script>

<style lang="scss">
page {
	pading: 0;
	height: 100%;
}

.chat {
	height: 100%;

	.goods {
		display: flex;
		position: fixed;
		width: 600rpx;
		right: 20rpx;
		bottom: calc(120rpx + env(safe-area-inset-bottom));
		border-radius: 14rpx;
		background: #fff;
		padding: 20rpx;

		.close {
			position: absolute;
			left: -20rpx;
			top: -20rpx;
		}

		.send-btn {
			padding: 8rpx 22rpx;
		}
	}

	.content {
		transition: all 0.3s;
		flex: 1;
		min-height: 0;

		.loading {
			padding: 20rpx;
			height: 40px;
		}

		.chat-lists {
			padding: 0 20rpx 30rpx;
			overflow: hidden;
			position: relative;

			.chat-tips {
				padding: 4rpx 20rpx;
				border-radius: 21rpx;
				display: inline-block;
				text-align: center;
				background-color: rgba(0, 0, 0, 0.2);
			}

			.chat-item {
				padding-top: 30rpx;

				&.visibility {
					visibility: hidden;
				}

				.chat-info {
					display: flex;
					align-items: flex-start;
				}

				&.right {
					.chat-info {
						flex-direction: row-reverse;

						.text-box {
							background-color: #ed5349;
							color: #fff;
						}
					}
				}

				.avatar {
					width: 78rpx;
					height: 78rpx;
					border-radius: 14rpx;
					flex: none;
				}

				.text-box {
					max-width: 500rpx;
					min-width: 80rpx;
					background-color: #fff;
					border-radius: 14rpx;
					padding: 16rpx 20rpx;
					margin: 0 20rpx;
					word-break: break-word;
					line-height: 40rpx;
				}

				.image-box {
					max-width: 300rpx;
					margin: 0 20rpx;

					.image {
						max-width: 100%;
					}
				}

				.goods-box {
					position: static;
					width: 510rpx;
				}
			}
		}
	}

	.error {
		padding: 0 30rpx 30rpx;

		.error-msg {
			color: #bbb;
			word-break: break-word;
		}
	}

	.footer {
		background: #f2f2f2;
		padding-bottom: env(safe-area-inset-bottom);

		.footer-input {
			height: 100rpx;
			padding: 0 20rpx;

			.icon {
				width: 52rpx;
				height: 52rpx;
			}

			.input-contain {
				margin: 0 20rpx;
				background-color: #fff;
				height: 68rpx;
				border-radius: 60rpx;
				flex: 1;
				overflow: hidden;
				padding: 0 10rpx 0 30rpx;

				.text-area {
					flex: 1;
					height: 100rpx;
					word-break: break-all;
				}
			}
		}
	}

	.emoji-wrap {
		height: 0;
		transition: all 0.3s;

		&.emoji-show {
			height: 200px;
		}
	}

	.send-btn {
		padding: 0 25rpx;
		color: #fff;
		background-color: #ed5349;
		border-radius: 60rpx;
	}
}
</style>
