<template>
	<view class="container">
		<button @click="onStartRecord" :disabled="isRecording">开始录音</button>
		<button @click="onStopRecord" :disabled="!isRecording">停止录音</button>
		<view class="tip">{{ status }}</view>
		<view class="tip">当前分贝：{{ currentDecibels }}</view>
		<yao-RecordFrame
			ref="recordFrame"
			@onFrameRecorded="frameRecorded"
			@currentDecibels="onCurrentDecibels"
			@onStop="stopIt"
		></yao-RecordFrame>
		<!-- <sdx-StreamPlayer ref="aaa">xx</sdx-StreamPlayer> -->
		<button @click="test">接通电话</button>
		<view
			ref="renderJSModule"
			:pcmChunk="currentPCMChunk"
			:change:pcmChunk="renderJS.appendPCMChunk"
			:isStop="isStop"
			:change:isStop="renderJS.stop"
			type="renderjs"
			module="renderJS"
		></view>
	</view>
</template>

<script>
	import {
		ProtocolCodec,
		MessageType,
		SerializationType,
		CompressionType,
		ControlCommand,
		ProtocolConst
	} from './ProtocolCodec';
	export default {
		data() {
			return {
				currentPCMChunk: null,
				isStop: false, // 停止播放指令
				status: '未录音',
				currentDecibels: 0,
				isRecording: false,
				ws: null, // WebSocket 实例
				audioContext: null, // 音频上下文
				scriptProcessor: null, // 音频处理节点
				audioBufferSource: null, // 音频源节点
				frameBufferList: [], // 缓存音频帧
				// wsUrl: "ws://127.0.0.1:8000/ws/audio", // 替换为实际后端地址
				// wsUrl: 'ws://172.16.89.58:8000/ws/audio' // 替换为实际后端地址
				// wsUrl: "ws://25.64.32.157:9603/trapractice/voiceCallSocket/voiceCall?summary=3D072C9D242C96EA3F0FD647CB14A6F4B4BEA4493BB2FAAB065935FB405071B8A903128E488B6D06BEB23FD4E3D15EE6", // 替换为实际后端地址
				wsUrl: "wss://aitstest.jlbank.com.cn:7001/trapractice/voiceCallSocket/voiceCall?summary=3D072C9D242C96EA3F0FD647CB14A6F44A8F9EF1C3D9726612B7339B566489139850DF3BE002DF99495FD60B34A5899D", // 替换为实际后端地址
			};
		},
		onUnload() {
			// 页面卸载时清理资源
			this.stopRecordAndClean();
		},
		methods: {
			test() {
				this.ws = uni.connectSocket({
					url: this.wsUrl,
					fail: () => {
						console.log('fail');
					},
					success: () => {
						console.log('web');
					},
					fail: () => {
						console.log('fail');
					}
				});
				this.ws.onOpen((res) => {
					console.log('WebSocket连接已打开', res);
					this.ws.send({
						data: ProtocolCodec.pack(MessageType.IDENTITY, {
							user_id: '1001',
							token: 'your_auth_token',
							name: '测试用户'
						})
					});
				});
				this.ws.onMessage((res) => {
					const { msgType, body } = ProtocolCodec.unpack(res.data);

					if (msgType === MessageType.IDENTITY) {
						console.log('身份校验成功', body);
						this.onStartRecord();
					} else if (msgType === MessageType.AUDIO_DATA) {
						// this.$refs.aaa.appendBuffer(body)
						// this.currentPCMChunk = body;
						const buffer = body;
						if (buffer.byteLength < 2) return;
						// ArrayBuffer转数字数组
						const uint8 = new Uint8Array(buffer);
						const numArray = Array.from(uint8);
						this.currentPCMChunk = numArray; // 传递数组
					} else {
						console.log('其他消息', body);
					}
				});
			},
			// 申请录音权限
			async applyRecordPermission() {
				try {
					const res = await uni.requestPermissions({
						scope: 'scope.record'
					});
					const isGranted = res[0].grantStatus === 1;
					if (!isGranted) {
						uni.showToast({
							title: '请授予录音权限',
							icon: 'none'
						});
					}
					return isGranted;
				} catch (e) {
					console.error('申请权限失败：', e);
					return false;
				}
			},
			// ArrayBuffer 转字符串
			// 兼容的 ArrayBuffer 转字符串方法
			arrayBufferToStringCompat(buffer) {
				// 方法1: 使用 String.fromCharCode 和 Uint8Array
				const uint8Array = new Uint8Array(buffer);
				let str = '';
				for (let i = 0; i < uint8Array.length; i++) {
					str += String.fromCharCode(uint8Array[i]);
				}
				return str;

				// 方法2: 或者使用更简洁的方式
				// return String.fromCharCode.apply(null, new Uint8Array(buffer));
			},
			// 开始录音
			onStartRecord() {
				console.log('开始录音');
				try {
					this.$refs.recordFrame.start({
						sampleRate: 16000,
						frameSize: 1024,
						gain: 1.0,
						onFrameRecorded: ({ isLastFrame, frameBuffer }) => {
							try {
								this.ws.send({
									data: ProtocolCodec.pack(MessageType.AUDIO_DATA, frameBuffer)
								});
							} catch (e) {}
						},
						onDecibels: (decibels) => {
							this.currentDecibels = decibels;
						}
					});
					this.isRecording = true;
					this.status = '录音中...';
				} catch (e) {
					console.error('启动录音失败：', e);
					this.status = '启动录音失败';
					this.isRecording = false;
				}
			},

			// 停止录音
			onStopRecord() {
				this.stopRecordAndClean();
			},

			// 停止录音并清理资源
			stopRecordAndClean() {
				if (this.isRecording) {
					// 停止录音组件
					this.$refs.recordFrame.stop();
					this.isRecording = false;
					this.status = '已停止录音';
				}

				// 关闭 WebSocket
				if (this.ws) {
					this.ws.close();
					this.ws = null;
				}

				// 清理音频上下文
				if (this.audioContext) {
					this.audioContext.close();
					this.audioContext = null;
					this.scriptProcessor = null;
					this.frameBufferList = [];
				}

				// 重置状态
				this.currentDecibels = 0;
			},

			// 接收音频帧并处理
			frameRecorded({ isLastFrame, frameBuffer }) {
				// console.log("收到音频帧：", isLastFrame, frameBuffer.length);

				// 2. 通过 WebSocket 发送给后端
				if (this.ws) {
					try {
						this.ws.send({
							data: frameBuffer
						});
					} catch (e) {
						console.error('发送音频帧失败：', e);
					}
				}
			},

			// 监听分贝值
			onCurrentDecibels(decibels) {
				// this.currentDecibels = decibels.toFixed(2);
				// console.log("当前分贝：", this.currentDecibels);
			},

			// 录音停止回调
			stopIt(base64) {
				this.stopRecordAndClean();
				console.log('录音停止，最终音频Base64：', base64?.substring(0, 50) + '...');
			}
		}
	};
</script>

<script module="renderJS" lang="renderjs">
	import { StreamPlayer } from ".//StreamPlayer";
	let player = null;

	export default {
	  mounted() {
	    const _this = this;
	    player = new StreamPlayer({
	      inputSampleRate: 44100, // 后端PCM采样率（如8000/24000）
	      numChannels: 1,         // 声道数（单声道/双声道）
	      bitDepth: 16,           // 位深（16/32bit）
	      littleEndian: true,     // 端序（和后端一致）
	      pcmType: 'int',         // 类型（int/float）
	      callback: _this.callback
	    });
	  },
	  methods: {
		  appendPCMChunk(numArray) {
				if (!numArray || numArray.length === 0) return;
				  // 数字数组转回ArrayBuffer
				  const uint8 = new Uint8Array(numArray);
				  const arrayBuffer = uint8.buffer;
				  
				  player.appendChunk(arrayBuffer);
		      },
	    // 停止播放（销毁播放器）
	    stop() {
	      if (player) {
	        player.destroy();
	        player = null;
	        // 重新初始化（方便后续再次播放）
	        const _this = this;
	        player = new StreamPlayer({
	          inputSampleRate: 16000,
	          numChannels: 1,
	          bitDepth: 16,
	          littleEndian: true,
	          pcmType: 'int',
	          callback: _this.callback
	        });
	      }
	    },

	    // 播放结束回调（通知主线程）
	    callback(e) {
	      if (e === 'ended') {
	        this.$ownerInstance.callMethod('changeStreamPlaying', { type: false });
	      }
	    }
	  }
	};
</script>

<style scoped>
	.container {
		padding: 20rpx;
	}

	button {
		margin: 10rpx 0;
		padding: 15rpx 30rpx;
		background: #007aff;
		color: white;
		border: none;
		border-radius: 8rpx;
	}

	button:disabled {
		background: #ccc;
	}

	.tip {
		margin: 15rpx 0;
		font-size: 28rpx;
		color: #333;
	}
</style>
