<template>
	<view class="sound-record-wrapper">
		<template v-if="type === 'big'">
			<view class="progress-box" v-if="file_url&&wavBlob">
				<text> {{ currentTime }} </text>
				<slider v-model="sliderValue" activeColor="#000000" block-size="12" @change="onSliderChange" />
				<text> {{ duration }} </text>
			</view>
			<view class="sound-item-box">
				<view class="sound-item">
					<view class="sound-item-svg" @click="handlePlay">
						<svg :fill="[wavBlob?'#1D1D1D':'#C3C3C3']" :style="{'width':iconSize,'height':iconSize}">
							<use :xlink:href="playing ? '#icon-stop' : '#icon-triangle'"></use>
						</svg>
					</view>
					<text class="sound-item-text" :style="{'color':wavBlob?'#1D1D1D':'#8C8C8C'}">回放</text>
				</view>
				<view v-if="viewPopup" class="sound-item" :style="{'opacity':disabled?'0.5':'1'}">
					<view class="sound-item-svg sound-item-microphone" @click="handleStart">
						<svg fill="#ffffff" :style="{'width':iconSize,'height':iconSize}">
							<use xlink:href="#icon-microphone"></use>
						</svg>
					</view>
					<text class="sound-item-text">录音</text>
				</view>
				<view v-else class="sound-item" :style="{'opacity':disabled?'0.5':'1'}">
					<view v-if="microphoneStatus" class="sound-item-img" @click="microphone">
						<img class="voice-play" src="static/record-ing-hasBg.png" />
					</view>
					<view v-else class="sound-item-svg sound-item-microphone" @click="microphone">
						<svg fill="#ffffff" :style="{'width':iconSize,'height':iconSize}">
							<use xlink:href="#icon-microphone"></use>
						</svg>
					</view>
					<text class="sound-item-text">
						{{ microphoneStatus ? secondFormatConversion(recordTimes) : '录音' }}
					</text>
				</view>
				<view class="sound-item" :style="{'opacity':disabled?'0.5':'1'}">
					<view class="sound-item-svg" :style="{'background-color':type === 'big'?'#f9f8f9':'#ffffff'}"
						@click="deleteWav">
						<svg :fill="[wavBlob?'#1D1D1D':'#C3C3C3']" :style="{'width':iconSize,'height':iconSize}">
							<use xlink:href="#icon-deletefile"></use>
						</svg>
					</view>
					<text v-if="type === 'big'" class="sound-item-text">删除</text>
				</view>
			</view>
		</template>
		<template v-else>
			<view class="sound-item-box">
				<view class="sound-item" :style="{'opacity':disabled?'0.5':'1'}">
					<view class="sound-item-svg sound-item-microphone" @click="handleStart">
						<svg fill="#ffffff" :style="{'width':iconSize,'height':iconSize}">
							<use xlink:href="#icon-microphone"></use>
						</svg>
					</view>
				</view>
				<view class="sound-item">
					<view class="progress-box" v-if="file_url&&wavBlob">
						<text> {{ currentTime }} </text>
						<slider v-model="sliderValue" activeColor="#000000" block-size="12" @change="onSliderChange" />
						<text> {{ duration }} </text>
					</view>
					<text class="sound-item-text" v-else>
						{{ secondFormatConversion(recordTimes) }}
					</text>
				</view>
				<view class="sound-item">
					<view class="sound-item-svg" style="background-color:#ffffff" @click="handlePlay">
						<svg :fill="[wavBlob?'#1D1D1D':'#C3C3C3']" :style="{'width':iconSize,'height':iconSize}">
							<use :xlink:href="playing ? '#icon-stop' : '#icon-triangle'"></use>
						</svg>
					</view>
				</view>
				<view class="sound-item" :style="{'opacity':disabled?'0.5':'1'}">
					<view class="sound-item-svg" :style="{'background-color':type === 'big'?'#f9f8f9':'#ffffff'}"
						@click="deleteWav">
						<svg :fill="[wavBlob?'#1D1D1D':'#C3C3C3']" :style="{'width':iconSize,'height':iconSize}">
							<use xlink:href="#icon-deletefile"></use>
						</svg>
					</view>
				</view>
			</view>
		</template>
		<uni-popup v-show="viewPopup" ref="popup" :mask-click="false">
			<view class="canvas-area">
				<text class="canvas-title">录音中...
					<text>{{ secondFormatConversion(recordTimes) }}</text>
				</text>
				<canvas canvas-id="recordCanvas" id="recordCanvas" type="2d" ref="record"></canvas>
				<view class="sound-item-svg" @click="handleStop">
					<svg fill="#ffffff">
						<use xlink:href="#icon-audio-stop"></use>
					</svg>
				</view>
			</view>
		</uni-popup>
	</view>
</template>

<script>
	import Recorder from 'js-audio-recorder'; // 录音插件
	import {
		GetStaticResources,
		GetFileStoreInfo
	} from '@/api/api.js';
	import {
		secondFormatConversion
	} from '@/utils/transform';
	export default {
		name: 'sound-record',
		props: {
			wavBlob: {
				type: String,
				default: '',
			},
			itemIndex: {
				type: Number,
				default: null,
			},
			type: {
				type: String,
				default: 'big',
			},
			notOnTheCurPage: {
				type: Boolean,
				default: false,
			},
			disabled: {
				type: Boolean,
				default: false,
			},
			viewPopup: {
				type: Boolean,
				default: true,
			}
		},
		data() {
			return {
				secondFormatConversion,
				microphoneStatus: false, //是否在录音
				recorder: new Recorder({
					sampleBits: 16, // 采样位数，支持 8 或 16，默认是16
					sampleRate: 16000, // 采样率，支持 11025、16000、22050、24000、44100、48000，根据浏览器默认值
					numChannels: 1, // 声道，支持 1 或 2， 默认是1
				}),
				timer: null, // 计时器
				recordTimes: 0,
				playtime: 0, //播放时间
				drawRecordId: null,
				audio: uni.createInnerAudioContext(),
				playing: false,
				file_url: '',
				duration: '00:00', //音频时长
				currentTime: '00:00', //当前时长
				sliderValue: 0,
			};
		},
		computed: {
			iconSize() {
				return this.type === 'big' ? 24 : 16;
			},
		},
		watch: {
			wavBlob: {
				handler(val) {
					if (!val) return;
					this.sliderValue = 0;
					GetFileStoreInfo({
						file_id: val
					}).then(({
						file_url,
						media_duration
					}) => {
						this.file_url = file_url;
						this.recordTime = media_duration;
						this.recordTimes = JSON.parse(JSON.parse(media_duration));
						this.audio.src = file_url;

						this.audio.onCanplay(() => {
							if (this.audio.duration !== 0) {
								clearInterval(this.intervalID);
								this.duration = this.secondFormatConversion(this.audio.duration) // 总时长
								this.currentTime = this.secondFormatConversion(this.audio.currentTime) // 当前时长
							}
						})
						this.audio.onTimeUpdate(() => {
							this.currentTime = this.secondFormatConversion(this.audio.currentTime);
							if (!this.dragging) { // 避免拖动滑块时自动更新
								this.sliderValue = (this.audio.currentTime / this.audio.duration) * 100;
							}
						})
					});
				},
				immediate: true,
			},
		},
		methods: {
			//不弹窗录音
			microphone() {
				if (this.disabled) return;
				if (this.microphoneStatus) {
					this.recorder.stop();
					this.sliderValue = 0;
					clearInterval(this.timer); //清除计时器
					this.microphoneStatus = false;
					// 录音结束，获取录音数据
					let wav = this.recorder.getWAVBlob(); // 获取 WAV 数据
					let reader = new window.FileReader();
					reader.readAsDataURL(wav);
					reader.onloadend = () => {
						let MethodName = 'file_store_manager-SaveFileByteBase64Text';
						let data = {
							base64_text: reader.result.replace('data:audio/wav;base64,', ''),
							file_suffix_name: 'mp3',
						};
						GetStaticResources(MethodName, data).then((res) => {
							if (res.status === 1) {
								this.$emit('update:wavBlob', res.file_id);
								this.$emit('setAudioId', res.file_id);
								this.audio.src = res.file_url;
								// console.log('文件', res);
							}
						});
					};
				} else {
					this.$emit('update:wavBlob', '');
					//获取录音权限
					Recorder.getPermission().then(() => {
						// 开始录音
						this.recorder.start().then(() => {
							this.microphoneStatus = true;
							this.sliderValue = 0;
							this.recordTimes = 0;
							clearInterval(this.timer);
							this.timer = setInterval(() => {
								this.recordTimes += 1;
								// console.log(this.recordTimes);
							}, 1000);
							// console.log('开始录音');
						})
					}, (error) => {
						console.log(`${error.name} : ${error.message}`)
					})
				}
			},
			// 开始录音
			handleStart() {
				if (this.disabled) return;
				//获取录音权限
				Recorder.getPermission().then(() => {
					this.recorder.start().then(() => {
						this.microphoneStatus = true;
						this.sliderValue = 0;
						//打开录音弹窗
						if (this.notOnTheCurPage) {
							uni.$emit('openOrClosePopup', true);
						} else {
							this.$refs.popup.open('center');
						}
						this.drawRecord();
						this.recordTimes = 0;
						clearInterval(this.timer);
						this.timer = setInterval(() => {
							this.recordTimes += 1;
						}, 1000);
						// console.log('开始录音');
					})
				}, (error) => {
					console.log(`${error.name} : ${error.message}`)
				})
			},
			// 停止录音
			handleStop() {
				this.recorder.stop();
				this.sliderValue = 0;
				//取消录音动画
				this.drawRecordId && cancelAnimationFrame(this.drawRecordId);
				this.drawRecordId = null;
				clearInterval(this.timer); //清除计时器
				this.microphoneStatus = false;
				//关闭录音弹窗
				if (!this.notOnTheCurPage) {
					this.$refs.popup.close();
				}
				// 录音结束，获取录音数据
				let wav = this.recorder.getWAVBlob(); // 获取 WAV 数据
				let reader = new window.FileReader();
				reader.readAsDataURL(wav);
				reader.onloadend = () => {
					let MethodName = 'file_store_manager-SaveFileByteBase64Text';
					let data = {
						base64_text: reader.result.replace('data:audio/wav;base64,', ''),
						file_suffix_name: 'mp3',
					};
					GetStaticResources(MethodName, data).then((res) => {
						if (res.status === 1) {
							this.$emit('update:wavBlob', res.file_id);
							this.$emit('setAudioId', res.file_id);
							this.audio.src = res.file_url;
							// console.log('文件', res);
						}
					});
				};
			},
			// 播放录音
			handlePlay() {
				if (this.wavBlob) {
					let totalTime = JSON.parse(JSON.stringify(this.recordTime));
					if (this.playing) {
						this.audio.pause();
						clearInterval(this.timer);
					} else {
						this.audio.play();
						clearInterval(this.timer);
						// 启动定时器，每秒更新一次进度条位置
						this.timer = setInterval(() => {
							if (this.audio.currentTime > 0 && this.audio.currentTime < this.audio.duration) {
								this.sliderValue = (this.audio.currentTime / this.audio.duration) * 100;
							} else {
								this.playing = !this.playing;
								clearInterval(this.timer);
							}
						}, 1000);
					}
					this.playing = !this.playing;
				}
			},
			// 删除录音
			deleteWav() {
				if (this.disabled) return;
				this.audio.pause();
				this.playing = false;
				this.microphoneStatus = false;
				this.playtime = 0;
				this.recordTimes = 0;
				this.file_url = '';
				clearInterval(this.timer);
				this.$emit('update:wavBlob', '');
				this.$emit('setAudioId', '');
			},
			// 录音波浪图
			drawRecord() {
				// 用requestAnimationFrame稳定60fps绘制
				this.drawRecordId = requestAnimationFrame(this.drawRecord);
				this.drawWave({
					dataArray: this.recorder.getRecordAnalyseData(),
				});
			},
			// 绘制波形图
			drawWave({
				dataArray
			}) {
				const ctx = uni.createCanvasContext('recordCanvas');
				const bufferLength = dataArray.length;
				ctx.rect(0, 0, 200, 64); //绘制矩形
				ctx.setFillStyle("#000000"); // 填充背景色
				// 设定波形,绘制颜色
				ctx.setLineWidth(2);
				ctx.setStrokeStyle("#ffffff");
				ctx.beginPath();
				var sliceWidth = (200 * 1.0) / bufferLength; // 一个点占多少位置，共有bufferLength个点要绘制
				var x = 0; // 绘制点的x轴位置
				for (var i = 0; i < bufferLength; i++) {
					var v = dataArray[i] / 128.0;
					var y = (v * 64) / 2;
					if (i === 0) {
						// 第一个点
						ctx.moveTo(x, y);
					} else {
						// 剩余的点
						ctx.lineTo(x, y);
					}
					// 依次平移，绘制所有点
					x += sliceWidth;
				}
				ctx.lineTo(200, 64 / 2);
				ctx.stroke();
				ctx.draw();
			},
			onSliderChange(event) {
				const value = event.detail.value;
				if (this.audio && this.audio.duration > 0) {
					// 验证 value 是否是有效的百分比值（0-100之间）
					if (isNaN(value) || value < 0 || value > 100) {
						// console.error("Invalid value:", value);
						return;
					}
					// 计算新的位置
					const newPosition = (value / 100) * this.audio.duration;
					// 验证 newPosition 是否是有效的数字，不是 NaN，并且在有效范围内
					if (!isNaN(newPosition) && newPosition >= 0 && newPosition <= this.audio.duration) {
						// 设置音频播放位置
						this.audio.seek(newPosition);
						if (!this.dragging) { // 避免拖动滑块时自动更新
							this.sliderValue = value;
						}
					} else {
						console.error("Invalid newPosition:", newPosition);
					}
				}
			},
		}
	};
</script>

<style lang="scss" scoped>
	.sound-record-wrapper {
		display: flex;
		flex-direction: column;
		margin-top: 32rpx;

		.progress-box {
			display: flex;
			justify-content: space-between;
			align-items: center;
			background-color: $uni-bg-color-grey;
			padding: 8rpx 16rpx;
			border-radius: 80rpx;
			font-size: 24rpx;
			column-gap: 26rpx;
			margin-bottom: 32rpx;

			slider {
				flex: 1;
				margin: 0;
			}
		}

		.sound-item-box {
			display: flex;
			align-items: center;
			justify-content: space-between;
			column-gap: 8rpx;

			.sound-item {
				text-align: center;

				.progress-box {
					margin: 0;

					slider {
						width: 100rpx;
						flex: 1;
						margin: 0;
					}
				}

				.sound-item-svg {
					padding: 20rpx;
					border-radius: 160rpx;
					background-color: $uni-bg-color-grey;
					display: flex;
					justify-content: center;
					align-items: center;
				}

				.sound-item-microphone {
					background-color: #7346d3;
				}

				.sound-item-img {
					display: flex;

					.voice-play {
						width: 84rpx;
						height: 84rpx;
					}
				}

				.sound-item-text {
					font-size: 24rpx;
					line-height: 40rpx;
				}
			}
		}

		.canvas-area {
			width: 308rpx;
			height: 312rpx;
			text-align: center;
			background-color: rgba(0, 0, 0, 0.8);
			border-radius: 32rpx;
			position: absolute;
			left: 50%;
			top: 50%;
			transform: translate(-50%, -50%);
			padding: 48rpx 32rpx;
			z-index: 111;

			.canvas-title {
				color: #ffffff;
				font-size: 28rpx;
			}

			canvas {
				width: 300rpx;
				height: 92rpx;
				margin: 46rpx 0;
			}

			.sound-item-svg {
				width: 96rpx;
				height: 96rpx;
				border-radius: 160rpx;
				background-color: #7346d3;
				display: flex;
				justify-content: center;
				align-items: center;
				margin: 0 auto;

				svg {
					width: 44rpx;
					height: 44rpx;
				}
			}
		}
	}
</style>