import type { SerialTaskExecuteContext } from '../handler'
import type { BusinessParams, PrivateCustomEventName } from '../types'
import { createWebSocket, objectToQueryString } from '@minto-ai/tools'

import { SerialHandler } from '../handler'
import { createEventBus } from '../utils'

const $bus = createEventBus<PrivateCustomEventName>()

const defaultBusinessParams: BusinessParams = {
  voice_type: 'zh_female_daimengchuanmei_moon_bigtts',
  speed_ratio: 1,
  volume_ratio: 1,
  pitch_ratio: 1,
  language: 'cn',

}

class TtsRequest extends SerialHandler<string, Blob> {
  private webSocketInstance: WebSocket | null = null

  private businessParams!: BusinessParams

  public initProperty(businessParams: Partial<BusinessParams>): void {
    this.businessParams = { ...defaultBusinessParams, ...businessParams }
  }

  public onActive(): void {
    this.webSocketInstance = createWebSocket(this.generateRequestUrl())
    this.webSocketInstance.addEventListener('message', (response: any) => {
      if (Object.prototype.toString.call(response.data) === '[object Blob]') {
        this.forwardToHandler(response.data)
      }
      else {
        const data = JSON.parse(response.data)
        if (data.event === 'sentence_end') {
          this.taskCompletedCallback()
        }
      }
    })
    this.webSocketInstance.addEventListener('open', () => {
      this.taskCompletedCallback()
    })
  }

  public executePreCheck(): boolean {
    return this.webSocketInstance?.readyState === WebSocket.OPEN
  }

  public execute(context: SerialTaskExecuteContext<string, Blob>): void {
    if (context.isLastExecute) {
      this.taskCompletedCallback()
      return
    }

    if (this.webSocketInstance) {
      this.webSocketInstance.send(JSON.stringify(this.generateRequestParams(context.taskItem.original!)))
    }
  }

  private generateRequestParams(text: string): {
    event: 'text'
    text: string

  } {
    return {
      event: 'text',
      text,
    }
  }

  private generateRequestUrl(): string {
    return `wss://audio.workbrain.cn/tts?${objectToQueryString({
      ...this.businessParams,
      stream: true,
    })}`
  }

  protected onFinish(): void {
    $bus.emit('_ttsRequestFinish')
    this.webSocketInstance?.close()
    this.webSocketInstance = null
  }
}

export default TtsRequest
