<template>
	<view class="content-body" v-if="info">
		<noticeBarOffset />

		<view v-if="playback || !anchor">
			<video :id="LIVE_ID" class="live-div" autoplay loop="true" @statechange="stateChange" @netstatus="netStatus" @error="error"
			 :src="addressSrc" :controls="playback" object-fit='cover'></video>

			<image v-if="!playConduct" :src="info.cover" class="live-div live-cover"></image>
		</view>

		<view v-else>
			<text class="err-tip">请到切换至APP</text>
		</view>

		<button v-if="info.videoAddressList.length>1" @tap="showVideoList" class="playback">视频列表</button>
		<text class="err-tip" v-if="!playConduct && tip">
			<text class="err-tip-title">{{info.name}}</text>
			<text class="err-tip-note">{{tip}}</text>
			<text v-if="tipTimeShow && timeInterval">
				<text class="err-tip-name">开播倒计时</text>
				<text class="err-tip-time">{{timeInterval}}</text>
			</text>
		</text>

		<slot :info="info"></slot>
		<view class="flex menu-top">
			<view class="home-div" @tap="navHome">
				<image mode="widthFix" class="back-home" :src="homeIcon"></image>
			</view>

			<view class="live-wa-top">
				<view class="user">
					<view class="top-item" style="padding-left: 0;">
						<image class="user-image" :src="info.users.userInfo.headPortrait || avatar"></image>
						<text class="live-id">ID:{{info.users.number}}</text>
					</view>
					<view class="item">
						<view class="user-text" style="margin-top: 0.2rem;">{{info.users.userInfo.name || APP_NAME}}</view>
						<view class="user-text number">观看: {{info.statistics.numberVisitors}}人</view>
					</view>
					<view class="item">
						<phoneLoginWrap>
							<button @click.stop="followEditReq" class="user-button">{{follow?'已关注':'关注'}}</button>
						</phoneLoginWrap>
					</view>
				</view>
				<view class="close" @click="closeClick">
					<image class="close-image" :src="closeIcon"></image>
				</view>
			</view>
		</view>

		<view class="live-wa-bottom" :class="playback && playConduct?`bottom-control`:null">
			<view class="note" v-if="!playback">
				{{config.prohibitionBroadcast || ``}}
			</view>

			<view style="position: relative;">
				<view class="new-message-tip flex" @tap="setMessageTop(true)" v-if="showNewMessage">
					<image class="new-message-tip-icon" :src="pullIcon" mode="widthFix"></image>
					<text class="new-message-tip-text">有新消息了点击查看</text>
				</view>
				<scroll-view :scroll-top="messageScrollTop" @scroll="scroll" class="live-wa-message" scroll-y="true"
				 @refresherrefresh="messageOldLoad" refresher-enabled scroll-with-animation="true" :refresher-triggered="refresherTriggeredMessage"
				 refresher-background="transparent">
					<view v-if="messages.length>0">
						<view class="item" :key="i" v-for="(m,i) in messages">
							<image class="span" :src="m.userInfo.headPortrait || avatar"></image>
							<text class="state span" :style="{backgroundColor:m.broadcastMessageConfig.nameBlockBgColor,color:m.broadcastMessageConfig.nameBlockColor}"
							 v-if="m.broadcastMessageConfig.nameBlockSurround">
								{{m.broadcastMessageConfig.nameBlockName}}
							</text>
							<text class="name span">
								{{m.userInfo.name}}:
							</text>
							<text class="span">{{m.content}}</text>
						</view>
					</view>
				</scroll-view>
			</view>

			<view class="operation-button" v-if="!messageShow">
				<view :key="i" v-for="(g,i) in operationButton" class="icon-view">
					<view :key="j" v-for="(item,j) in g">
						<share v-if="item.share" ref="share">
							<op :info="info" @update="opTap" :item="item"></op>
						</share>
						<op :info="info" @update="opTap" v-else :item="item"></op>
					</view>
				</view>
			</view>
			<view class="message-input" v-if="messageShow">
				<input class="message-input-side" v-model="message" placeholder="完整的描述，才能更好的回答问题哦～" />
				<button class="message-input-button" @click="messageSwitch">{{message===''?'取消':'发送'}}</button>
			</view>
		</view>
		<productPopup @toggleSpec="toggleSpecProduct" :list="getcommodityInfoList()" :show="productPopupShow"></productPopup>
		<posterPopup @toggleSpec="toggleSpecPoster" :live="info" :show="posterPopupShow"></posterPopup>

		<connect @select="selectConnect" :list="shareList" @toggleSpec="toggleSpecConnect" :show="connectPopupShow"></connect>
	</view>
</template>

<script>
	import {
		mapState
	} from 'vuex'
	import noticeBarOffset from "../notice-bar-offset"
	import op from './broadcast-op'
	import productPopup from '../product-popup'
	import posterPopup from '../live/poster'
	import share from '../share'
	import connect from '../wrap/connect.vue'
	import wxIcon from '../../static/wx.svg'
	import posterIcon from '../../static/poster.svg'
	import homeIcon from '../../static/home.svg'
	import pullIcon from '../../static/pull.svg'

	import {
		cameraView,
		shareView,
		bagView,
		messageView,
		zanView,
		collectionView,
		playbackView
	} from '../../js/live.js'

	import {
		loopLiveRoomInfo,
		theEndLiveRoom,
		theStartLiveRoom,
		sendChatLiveRoom,
		liveRoomWs,
		getUserToken,
		findRoomMessageList,
		followFind,
		followEdit,
		staticUrl,
		navToInfoLive,
		configGetLiveRecordProperites,
		profile,
		twoTimeInterval
	} from '../../js/request.js'

	const LIVE_ID = "live"
	const classUse = 'live-wa-message'
	const avatar = staticUrl('/icon/live-close.png')
	const closeIcon = staticUrl('/icon/live-close.png')

	const stateTip = {
		"END": `此场直播已经结束`,
		"CANCEL": `此场直播已经取消`,
		"PREPARE": `此场直播正在预备中`
	}

	export default {
		components: {
			noticeBarOffset,
			op,
			productPopup,
			share,
			posterPopup,
			connect
		},
		computed: {
			...mapState(['userToken'])
		},
		props: ['anchor', 'playback', 'liveId'],
		mounted() {
			this.checkLogin()
			this.configGetLiveRecordProperitesLoop()
			// #ifdef MP,APP-PLUS
			try {
				if (this.anchor) {
					this.context = uni.createLivePusherContext(LIVE_ID, this)
					this.context.startPreview({
						success: (a) => {
							console.log("livePusher.startPreview:" + JSON.stringify(a));
						}
					});
					// 开始推流
					this.context.start({
						success: (a) => {
							console.log("livePusher.start:" + JSON.stringify(a));
						}
					});
				} else {
					this.context = uni.createLivePlayerContext(LIVE_ID, this)
				}
			} catch (e) {
				this.$info("Create createLivePusherContext || createLivePusherContext Fail", e)
			}
			// #endif

			this.initializationData()
			this.refreshLive()
		},
		data() {
			const {
				screenHeight
			} = uni.getSystemInfoSync()

			return {
				shareList: [{
						icon: posterIcon,
						text: `生成海报`
					},
					{
						icon: wxIcon,
						text: `分享到微信`,
						share: true
					}
				],
				pullIcon,
				homeIcon,
				wsCount: 0,
				playConduct: true,
				videoRetry: false, // 播放或录制重试
				forcedLogin: false, // 强制登陆
				stateTip,
				refresherTriggeredMessage: false,
				follow: false,
				messageScroll: true,
				old: {
					messageScroll: 0,
					max: 0,
					distance: 10
				},
				messageScrollTop: 10,
				messageHeight: 0,
				messageLastId: null,
				globalMonitoringWs: false,
				messageEnableWs: true,
				messages: [],
				operationButton: [],
				avatar,
				closeIcon,
				messageShow: false,
				message: '',
				posterPopupShow: false,
				productPopupShow: false,
				connectPopupShow: false,
				info: null,
				...{
					LIVE_ID,
					classUse
				},
				pageNum: 1,
				screenHeight: screenHeight + 2,
				addressSrc: null,
				config: {},
				tip: null,
				tipTimeShow: false,
				timeInterval: null,
				showNewMessage: false,
				tipNewMessageDelay: 3000,
				tipNewMessageTypes: ['CHAT'],
				enableRefresh: false
			}
		},
		watch: {
			userToken(val) {
				this.initializationData()
			},
			messages: {
				handler() {
					this.$nextTick(() => {
						uni.createSelectorQuery().select(`.${classUse}`)
							.boundingClientRect(data => {
								this.messageHeight = data ? data.bottom : 0
							})
							.exec()
						this.setMessageTop()
					})
				},
				immediate: true,
				deep: true
			},
			info(newData, old) {
				const tip = this.setTip(newData)
				if (!old && newData) {
					this.$emit("updateLiveInfo", newData)
				}
				if (tip && !this.hasPlayAddress(newData)) {
					this.playConduct = false
				} else {
					this.playConduct = true
				}
			}
		},
		methods: {
			twoTimeInterval,
			setTip(live = this.info) {
				let tip = `正在加载中`
				if (live) tip = stateTip[live.liveState]
				this.tip = tip
				return tip
			},
			async checkLogin() {
				if (this.forcedLogin) await profile()
			},
			async configGetLiveRecordProperitesLoop() {
				this.config = await configGetLiveRecordProperites()
			},
			setNewMessageTip(message) {
				const that = this
				const messageType = message.messageType
				if (messageType && this.tipNewMessageTypes.indexOf(messageType) !== -1 &&
					!this.showNewMessage && !this.messageScroll) {
					that.showNewMessage = true

					setTimeout(() => {
						if (that.showNewMessage) that.showNewMessage = false
					}, that.tipNewMessageDelay)
				}
			},
			async initializationData() {
				await this.getInfo()
				//ws
				this.liveRoomWsOpen()

				//加载历史消息
				this.messageOldLoad()

				//关注查询
				this.followFindReq()

				if (this.anchor && this.info) this.theStartLiveRoomRequest()
			},
			refreshLive() {
				if (!this.enableRefresh) return
				setInterval(() => {
					this.getInfo()
				}, 5000)
			},
			updteTime(info = this.info) {
				if (!info) {
					this.tipTimeShow = false
				} else {
					this.tipTimeShow = info.liveState === `PREPARE`

					if (this.tipTimeShow) {
						this.timeInterval = twoTimeInterval(new Date(), new Date(info.startDateEstimate))
					}
				}
			},
			async getInfo() {
				let info = loopLiveRoomInfo()
				const liveId = this.liveId
				try {
					if (liveId && liveId !== 'null') info = await navToInfoLive(liveId, true)
				} catch (e) {
					console.log(e.message)
				}

				let addressSrc = (info.playerAddressList || [{}]).filter(it => it.type === 'M3U8')[0].address
				if (this.playback) {
					addressSrc = (info.videoAddressList || [])[0]
				} else {
					if (info.liveState === 'END') addressSrc = null
				}

				if (info.videoAddressList.length > 0 && !this.playback) {
					uni.redirectTo({
						url: `/pages/live/playback?id=${liveId}`
					})
				}

				this.updteTime(info)

				const message = messageView(this)
				const zan = zanView(this)
				const share = shareView(this)
				const bag = bagView(this)
				const camera = cameraView(this)
				const collection = collectionView(this)
				const playback = playbackView(this)


				bag.dot = this.getcommodityInfoList(info).length
				zan.ok = info.fabulous
				zan.content = info.fabulousSum

				collection.ok = info.collection
				collection.content = info.collectionSum

				let operationButton = !this.anchor ? [
					[message, zan, collection],
					[bag, share]
				] : [
					[camera],
					[bag, share]
				]

				if (this.playback) {
					operationButton = [
						[playback],
						[bag, share]
					]
				}

				this.info = info
				this.operationButton = operationButton
				this.addressSrc = addressSrc
			},
			scroll(e) {
				const top = e.detail.scrollTop
				if (top > this.old.max) this.old.max = top
				this.old.messageScrollTop = top
				this.messageScroll = !(this.old.max - this.old.messageScrollTop >= this.old.distance)
			},
			async followEditReq() {
				if (!this.info) return
				const status = this.follow ? "0" : "1"
				await followEdit({
					user_id: this.info.users.userInfo.id,
					status
				})
				this.follow = !this.follow
			},
			async followFindReq() {
				if (!this.info) return
				const {
					data
				} = await followFind({
					user_id: this.info.users.userInfo.id
				})
				this.follow = data
			},
			setMessageTop(force = false) {
				if (this.messageScroll || force) {
					this.showNewMessage = false
					this.messageScrollTop = 0
					this.$nextTick(function() {
						this.messageScrollTop = this.messageHeight + 10000
					})
				}
			},
			async theStartLiveRoomRequest(id = this.info.id) {
				await theStartLiveRoom(id)
			},
			async messageOldLoad() {
				this.findRoomMessageListReq(false)
			},
			async findRoomMessageListReq(findingDirection = true) {
				if (!this.info) return
				if (this.messageLastId) {
					this.refresherTriggeredMessage = true
				}

				const page = await findRoomMessageList({
					roomId: this.info.id,
					findingDirection,
					findingLastId: this.messageLastId,
					pageNum: this.pageNum
				})

				const empty = page.empty
				if (!empty) {
					const content = page.content.reverse()

					if (this.messageLastId) {
						this.messages = [...content, ...this.messages]
					} else {
						this.messages = [...this.messages, ...content]
					}


					this.messageLastId = content[0].id
				}

				this.refresherTriggeredMessage = false
			},
			hasPlayAddress(live = this.info) {
				if (!live) return false
				const state = live.liveState
				if (live === `CONDUCT`) {
					return true
				} else {
					return live.videoAddressList.length > 0
				}
			},
			async liveRoomWsOpen() {
				this.wsCount++
				if (this.wsCount >= 5) return
				const that = this
				if (!this.info) return

				if (that.socketTask) {
					that.socketTask.close()
				}

				let userToken = getUserToken()
				if (!userToken) userToken = "-1"
				const socketTask = await liveRoomWs(userToken, this.info.id)

				that.socketTask = socketTask

				const reconnect = (e) => {
					that.$error(`Chat WS Disconnected reconnecting`, e || false)
					setTimeout(() => that.liveRoomWsOpen(), 1000 * 30) // WS重连
				}

				const successTip = (e) => {
					that.$info('Char liveRoomWsOpen Success', e || true)
				}

				const acceptanceMessage = (e) => {
					that.$info(`acceptanceMessage Chat`, e)
					const data = JSON.parse(e.data)

					if (data) {
						that.setNewMessageTip(data)

						//状态更新
						if (data.messageType === `STATE_LIVE`) {
							that.getInfo()
						}

						if (!data.numberVisitors) {
							that.messages.push(data)
						} else {
							that.info.statistics = data
							that.info.fabulousSum = data.numberGiveThumbs
							that.info.collectionSum = data.numberCollection
						}
					}
				}

				if (this.globalMonitoringWs) {
					uni.onSocketOpen(successTip)
					uni.onSocketError(reconnect)
					uni.onSocketClose(reconnect)
					uni.onSocketMessage(acceptanceMessage)
				} else {
					socketTask.onClose(reconnect)
					socketTask.onError(reconnect)
					socketTask.onOpen(successTip)
					socketTask.onMessage(acceptanceMessage)
				}
			},
			opTap(item) {
				this.$info('opTap Update Data', item)
				if (item.message) this.messageSwitch()
				if (item.share) this.$refs.share[0].toggleMask()
				if (item.bag) this.productPopupShow = !this.productPopupShow
				if (item.camera) this.switchCamera()

				if (item.shareBut) {
					this.connectPopupShow = true
				}
			},
			toggleSpecProduct(val) {
				this.productPopupShow = val
			},
			toggleSpecPoster(val) {
				this.posterPopupShow = val
			},
			toggleSpecConnect(val) {
				this.connectPopupShow = val
			},
			selectConnect(it) {
				if (!it.share) {
					this.toggleSpecPoster(true)
					this.toggleSpecConnect(false)
				}
			},
			showVideoList() {
				const that = this
				const live = this.info
				const length = live.videoAddressList.length
				const itemList = []
				for (var i = 0; i < length; i++) {
					itemList.push(`第${i+1}段录播`)
				}
				uni.showActionSheet({
					itemList,
					success(res) {
						that.addressSrc = live.videoAddressList[res.tapIndex]
					}
				})
			},
			async messageSwitch() {
				const that = this
				const message = this.message
				const success = () => this.$api.msg(`发送成功`)

				if (message !== '') {
					if (this.messageEnableWs) {
						this.socketTask.send({
							data: message,
							fail(e) {
								that.$error(`Chat message send fail`, e)
							},
							success
						})
					} else {
						await sendChatLiveRoom(this.info.id, message)
						success()
					}
				}
				this.message = ''
				this.messageShow = !this.messageShow
			},
			getcommodityInfoList(info = this.info || {}) {
				return info.commodityInfoList || []
			},
			switchCamera() {
				const that = this
				this.context.switchCamera({
					success(a) {
						that.$info(`switchCamera:Success`, a)
						that.$api.msg(`摄像头切换成功`)
					}
				})
			},
			navHome() {
				uni.reLaunch({
					url: '/pages/main/index'
				})
			},
			stateChange(e) {
				this.$info('stateChange data', e)
			},
			netStatus(e) {
				this.$info('netStatus data', e)
			},
			error(e) {
				this.playConduct = false
				const name = this.anchor ? '录制' : '播放'
				this.$error("Pusher & Play Falil:", e)
				const that = this

				if (!this.videoRetry) return

				uni.showModal({
					content: `${name}失败，是否重试?`,
					success: (e) => {
						if (e.confirm) {
							if (!that.context) return
							if (that.anchor) {
								that.context.start({
									fail(e) {
										that.error(e)
									}
								})
							} else {
								that.context.play({
									fail(e) {
										that.error(e)
									}
								})
							}
						} else {
							uni.navigateBack()
						}
					}
				})
			},
			async closeClick() {
				const that = this
				const id = this.info.id
				if (this.anchor) {
					uni.showModal({
						content: '确认结束吗？',
						success: (e) => {
							if (e.confirm) {
								//停止推流
								that.context.stop({
									success: (a) => {
										console.log(JSON.stringify(a))
									}
								})
								theEndLiveRoom(id).then()
								uni.navigateTo({
									url: '/pages/result/live'
								})
							}
						}
					})
				} else {
					uni.navigateBack()
				}
			}
		}
	}
</script>


<style lang="scss" scoped>
	$border-radius:5rem;
	$padding: 10upx;
	$min-font-size: 22upx;
	$body-margin: 20upx;

	.new-message-tip {
		$padding: 15upx;
		position: absolute;
		left: 0;
		right: 0;
		margin: 0 auto;
		top: 50%;
		z-index: 9999;
		background-color: #000000;
		align-items: center;
		padding: $padding;
		border-radius: 50upx;
		width: max-content;

		$size: 30upx;

		&-icon {
			width: $size;
		}

		&-text {
			font-size: $size;
		}
	}

	.live-cover {
		filter: blur(10upx);
	}

	.menu-top {
		align-items: center;
	}

	.back-home {
		width: 60upx;
		vertical-align: middle;
	}

	.home-div {
		z-index: 9999;
		position: relative;
		background-color: $background-color;
		border-radius: 50%;
	}

	.live-div {
		position: fixed;
		top: 0;
		left: 0;
		width: 100%;
		height: 100%;
	}

	.content-body {
		width: 100%;
		position: absolute;
		margin: $body-margin;
		color: #FFFFFF;
		height: calc(100% - (#{$body-margin} * 2));
	}

	.message-input {
		background-color: $background-color;
		flex-direction: row;
		justify-content: space-between;
		padding: 10upx;
		display: flex;

		input {
			background-color: #FFFFFF;
			width: 80%;
			line-height: 80upx;
			height: 80upx;
			color: $background-color;
			border-radius: 5rem;
			padding: 0 1rem;
			font-size: 0.7rem;
		}

		button {
			width: 20%;
			margin: 0 10upx;
			background-color: #F5B59A;
		}
	}

	.live-wa-bottom {
		position: fixed;
		bottom: 0;
		z-index: 2;
		width: calc(100% - #{$body-margin * 2});

		.note {
			width: 60%;
			background-color: $background-color;
			padding: $padding;
			border-radius: 20upx;
			font-size: 0.7rem;
		}
	}

	.bottom-control {
		margin-bottom: 2rem;
	}

	.operation-button {
		display: flex;
		justify-content: space-between;
		flex-direction: row;
		margin: 10px 0;

		.icon-view {
			flex-direction: row;
			display: flex;
		}

		.item {
			margin: $padding;
		}
	}

	.live-wa-message {
		$font-size: .8rem;
		height: 350upx;
		font-size: $font-size;

		.item {
			$m: $padding / 2;
			border-radius: 20upx;
			background-color: $background-color;
			padding: $m;
			margin: $m 0;
			flex-direction: row;
			flex-wrap: wrap;

			image {
				$size: 1rem;
				border-radius: 50%;
				height: $size;
				width: $size;
				vertical-align: middle;
			}

			.state {
				background-color: #DB2424;
				border-radius: 10upx;
				padding: $padding / 2 $padding;
				font-size: .6rem;
				height: 100%;
			}

			.span {
				margin-right: 10upx;
			}

			.name {
				color: #CAC8C1;
			}
		}
	}

	.live-wa-top {
		$text-size: 0.8rem;
		$line-height: $text-size + 0.3rem;
		$height: $line-height * 2;
		margin-left: 2.5%;

		width: 95%;
		display: flex;
		justify-content: space-between;
		flex-direction: row;
		align-items: center;

		.item {
			padding: 0 $padding;
		}

		.user {
			align-items: center;
			background-color: $background-color;
			border-radius: $border-radius;
			display: flex;
			position: relative;
			justify-content: space-between;
			padding-right: $padding;
			flex-direction: row;

			.text {
				font-size: $text-size;
				line-height: $line-height;
				text-align: center;
			}

			.number {
				font-size: $min-font-size;
			}

			image {
				$add-size: 0.2rem;
				$size: $height + $add-size;
				border-radius: 50%;
				height: $size;
				width: $size;
				position: relative;
				left: -$add-size;
			}

			.live-id {
				background: #D09780;
				border-radius: $border-radius;
				font-size: 18upx;
				position: absolute;
				left: -10upx;
				bottom: 0;
				padding: 0 $padding;
			}

			button {
				$n: 1.5;
				$b-hei: 60upx;
				background: url('../../static/live-follow.png');
				background-size: 100% 100%;
				height: $b-hei;
				line-height: $b-hei;
				color: #FFFFFF;
			}


		}

		.close {
			padding: $padding;
			margin-right: 20upx;

			image {
				$size: 1.5rem;
				border-radius: $border-radius;
				height: $size;
				width: $size;
				position: relative;
				top: $height/4;

				/* #ifdef MP */
				top: $height + 0rem;
				/* #endif */
			}
		}
	}

	button::after {
		border: 0 !important;
	}

	.err-tip {
		$size: 46upx;
		$height: $size + $size / 2;
		position: absolute;
		width: 80%;
		text-align: center;
		left: 0;
		right: 0;
		top: -170upx;
		bottom: 0;
		margin: auto;
		color: darkred;
		font-size: $size;
		height: $height;
		line-height: $height;
	}

	.err-tip-title {
		color: #FFFFFF;
		font-weight: 600;
		display: block;
		background-color: $background-color;
	}

	.err-tip-note {
		display: block;
		background-color: $background-color;
	}

	.err-tip-name {
		font-size: 22upx;
		display: block;
		background-color: $background-color;
	}

	.err-tip-time {
		color: #FFFFFF;
		font-weight: 600;
		display: block;
		background-color: $background-color;
	}

	.playback {
		position: absolute;
		right: 30upx;
		top: 130upx;
		bottom: 0;
		width: 200upx;
		transform: scale(0.5);
		height: 80rpx;
	}
</style>
