// recordingPlugin.js
export default {
  install (Vue) {
    Vue.prototype.$recording = {
      isRecording: false, // 标识是否正在录音
      mediaRecorder: null, // MediaRecorder 实例
      audioChunks: [], // 存储录音数据块
      audioUrl: null, // 录音生成的 URL
      inputData: '',
      audioContext: null,
      audioStream: null,
      ws: null,
      resolvePromise: null, // 用于保存 Promise 的 resolve 函数

      async startRecording () {
        this.inputData = ''
        this.audioChunks = []

        const url = 'ws://192.168.50.67:30288/websocket/bash' // WebSocket地址
        this.setupWebSocket(url)

        // 等待 WebSocket 连接成功
        const result = await this.waitForWebSocketConnection()

        if (result) {
          return {
            code: 500,
            msg: result
          }
        }

        this.isRecording = true

        // 初始化 AudioContext
        this.audioContext = new (window.AudioContext || window.webkitAudioContext)()

        if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
          this.ws.close()
          return {
            code: 500,
            msg: '录音软件不支持您的浏览器！请使用现代浏览器或确保您正在使用 HTTPS。'
          }
        }
        // 获取麦克风输入流
        this.audioStream = await navigator.mediaDevices.getUserMedia({ audio: true })

        // 设置音频处理流程
        this.setupAudioProcessing()

        return {
          code: 200,
          msg: '开始录音'
        }
      },

      setupWebSocket (url) {
        this.ws = new WebSocket(url)

        this.ws.onmessage = (event) => {
          const data = JSON.parse(event.data)
          console.log('Result:', data.result)
          if (data.result !== undefined) {
            this.inputData += data.result
          }
          if (!this.isRecording) {
            this.ws.close()
          }
        }

        this.ws.onclose = () => {
          console.log('WebSocket closed.')
          this.resRecordingData()
          this.resolvePromise(this.inputData)
      }
        this.ws.onerror = (error) => console.error('WebSocket error:', error)
      },

      waitForWebSocketConnection () {
        return new Promise((resolve) => {
          this.ws.onopen = () => {
            console.log('WebSocket 连接成功')
            resolve()
          }

          this.ws.onerror = (error) => {
            resolve('WebSocket 连接失败: ' + error.message)
          }
        })
      },

      setupAudioProcessing () {
        try {
          const source = this.audioContext.createMediaStreamSource(this.audioStream)
          const processor = this.audioContext.createScriptProcessor(4096, 1, 1)

          processor.onaudioprocess = (e) => {
            // if (!this.isRecording) return

            const inputData = e.inputBuffer.getChannelData(0)

            // Resample to 16000 Hz if needed
            const resampledData = this.resample(inputData, this.audioContext.sampleRate, 16000)

            this.audioChunks.push(new Float32Array(resampledData))

            // Convert to 16-bit PCM and send via WebSocket
            const byteArray = this.convertTo16BitPCM(resampledData)

            const finalData = new Uint8Array(1 + byteArray.length) // 创建最终数据数组
            finalData[0] = 1 // 第一个字节为类型，值为1
            finalData.set(byteArray, 1) // 设置实际数据

            this.ws.send(finalData) // 发送最终数据
          }

          source.connect(processor)
          processor.connect(this.audioContext.destination)
          return {
            code: 200,
            msg: '录音初始化成功'
          }
        } catch (error) {
          console.error('Error setting up audio processing:', error)
          return {
            code: 500,
            msg: '录音初始化出错：' + error.message
          }
        }
      },

      stopRecording () {
        console.log('停止录音')

        // 停止麦克风流
        if (this.audioStream) {
          this.audioStream.getTracks().forEach((track) => track.stop())
        }

        if (this.audioContext) {
          this.audioContext.close()
        }

        // 发送结束信号
        const endSignal = new Uint8Array(1) // 创建一个长度为1的Uint8Array
        endSignal[0] = 2 // 直接发送类型，值为2
        this.ws.send(endSignal) // 发送结束信号

        this.isRecording = false

        return {
          code: 200,
          msg: '录音已停止'
        }
      },

      saveAudioFile () {
        const audioBuffer = this.mergeAudioChunks(this.audioChunks)

        // 转换为 WAV 格式
        const wavBlob = this.encodeWAV(audioBuffer, 16000)

        // 创建下载链接并触发下载
        const url = URL.createObjectURL(wavBlob)
        const a = document.createElement('a')
        a.style.display = 'none'
        a.href = url
        a.download = 'recording.wav'
        document.body.appendChild(a)
        a.click()
        window.URL.revokeObjectURL(url)
      },

      mergeAudioChunks (chunks) {
        const length = chunks.reduce((sum, chunk) => sum + chunk.length, 0)
        const result = new Float32Array(length)
        let offset = 0
        for (const chunk of chunks) {
          result.set(chunk, offset)
          offset += chunk.length
        }
        return result
      },

      encodeWAV (samples, sampleRate) {
        const buffer = new ArrayBuffer(44 + samples.length * 2)
        const view = new DataView(buffer)

        const writeString = (view, offset, string) => {
          for (let i = 0; i < string.length; i++) {
            view.setUint8(offset + i, string.charCodeAt(i))
          }
        }

        writeString(view, 0, 'RIFF')
        view.setUint32(4, 36 + samples.length * 2, true)
        writeString(view, 8, 'WAVE')

        writeString(view, 12, 'fmt ')
        view.setUint32(16, 16, true)
        view.setUint16(20, 1, true)
        view.setUint16(22, 1, true)
        view.setUint32(24, sampleRate, true)
        view.setUint32(28, sampleRate * 2, true)
        view.setUint16(32, 2, true)
        view.setUint16(34, 16, true)

        writeString(view, 36, 'data')
        view.setUint32(40, samples.length * 2, true)

        let offset = 44
        for (let i = 0; i < samples.length; i++) {
          const s = Math.max(-1, Math.min(1, samples[i]))
          view.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7fff, true)
          offset += 2
        }

        return new Blob([buffer], { type: 'audio/wav' })
      },

      resample (data, inputSampleRate, outputSampleRate) {
        if (inputSampleRate === outputSampleRate) {
          return data
        }
        const sampleRateRatio = inputSampleRate / outputSampleRate
        const newLength = Math.round(data.length / sampleRateRatio)
        const resampledData = new Float32Array(newLength)
        for (let i = 0; i < newLength; i++) {
          const index = Math.round(i * sampleRateRatio)
          resampledData[i] = data[index]
        }
        return resampledData
      },

      convertTo16BitPCM (data) {
        const output = new Int16Array(data.length)
        for (let i = 0; i < data.length; i++) {
          output[i] = Math.max(-1, Math.min(1, data[i])) * 0x7fff
        }
        return new Uint8Array(output.buffer)
      },

      async getRecordingData () {
        return new Promise((resolve) => {
          this.resolvePromise = resolve

          if (!this.ws) {
            // 如果 WebSocket 未初始化，直接拒绝
            console.log('错误结束')
            resolve(this.inputData)
          }
        })
      },

      resRecordingData () {
      }
    }
  }
}
