import { WebSocket } from 'ws';
import '../lib/cryptojs.js';

var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;

export class NewCredential {
  constructor(query) {
    this.config = {
      appid: query.appid,
      secretid: query.secretid,
      token: query.token
    };
    this.query = query || null;
  }

  formatSignString(params) {
    let strParam = "";
    let signStr = "asr.cloud.tencent.com/asr/v2/";
    if (this.config['appid']) {
      signStr += this.config['appid'];
    }
    const keys = Object.keys(params);
    keys.sort();
    for (let i = 0, len = keys.length; i < len; i++) {
      strParam += `&${keys[i]}=${params[keys[i]]}`;
    }
    return `${signStr}?${strParam.slice(1)}`;
  }
  async createQuery() {
    const params = {};
    const time = new Date().getTime();
    const guid = () => {
      return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        const r = Math.random() * 16 | 0,
          v = c === 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
      });
    };

    async function getServerTime() {
      return new Promise((resolve, reject) => {
        try {
          const xhr = new XMLHttpRequest();
          xhr.open("GET", 'https://asr.cloud.tencent.com/server_time', true);
          xhr.send();
          xhr.onreadystatechange = function () {
            if (xhr.readyState === 4 && xhr.status === 200) {
              resolve(xhr.responseText);
            }
          }
        } catch (error) {
          reject(error);
        }
      })
    }
    const serverTime = await getServerTime();
    params['secretid'] = this.config.secretid || '';
    params['engine_model_type'] = this.query.engine_model_type || '16k_zh';
    params['timestamp'] = parseInt(serverTime) || Math.round(time / 1000);
    params['expired'] = Math.round(time / 1000) + 24 * 60 * 60;
    params['nonce'] = Math.round(time / 100000);
    params['voice_id'] = guid();

    // 非必填参数
    this.query.hasOwnProperty('voice_format') && (params['voice_format'] = this.query.voice_format);
    this.query.hasOwnProperty('hotword_id') && (params['hotword_id'] = this.query.hotword_id);
    this.query.hasOwnProperty('needvad') && (params['needvad'] = this.query.needvad);
    this.query.hasOwnProperty('filter_dirty') && (params['filter_dirty'] = this.query.filter_dirty);
    this.query.hasOwnProperty('filter_modal') && (params['filter_modal'] = this.query.filter_modal);
    this.query.hasOwnProperty('filter_punc') && (params['filter_punc'] = this.query.filter_punc);
    this.query.hasOwnProperty('convert_num_mode') && (params['convert_num_mode'] = this.query.convert_num_mode);
    this.query.hasOwnProperty('word_info') && (params['word_info'] = this.query.word_info);
    this.query.hasOwnProperty('vad_silence_time') && (params['vad_silence_time'] = this.query.vad_silence_time);

    this.config.token && (params['token'] = this.config.token);

    return params;
  }
  // 获取签名原文
  async getSignStr() {
    const queryStr = await this.createQuery();
    return this.formatSignString(queryStr);
  }
}

export default class SpeechRecognizer {
  constructor(params) {
    this.appid = params.appid || ''
    this.secretid = params.secretid || ''
    this.socket = null;
    this.isSignSuccess = false; // 是否鉴权成功
    this.isSentenceBegin = false; // 是否一句话开始
    this.query = {
      ...params
    };
    // 用户鉴权函数
    this.signCallback = params.signCallback || null;
    this.isRecognizeComplete = false; // 当前是否识别结束
  }
  // 暂停识别，关闭连接
  stop() {
    if (this.socket && this.socket.readyState === 1) {
      this.socket.send(JSON.stringify({ type: 'end' }));
      console.log('【Tencent ASR】stop');
    } else {
      this.OnError('连接未建立或连接已关闭');
      if (this.socket && this.socket.readyState === 1) {
        this.socket.close();
      }
    }
  }
  // 拼接鉴权数据
  async getUrl() {
    if (!this.appid || !this.secretid) {
      this.OnError('请确认是否填入appid和secretid');
      return false
    }
    const asr = new NewCredential(this.query);
    const signStr = await asr.getSignStr();
    const result =`${signStr}&signature=${encodeURIComponent(this.signCallback(signStr))}`;
    console.log(result);
    return result;
  }
  // 建立websocket链接 data 为用户收集的音频数据
  async start() {
    const url = await this.getUrl();
    console.log("【Tencent ASR】connect URL:======>",url);
    if (!url) {
      this.OnError('鉴权失败');
      return
    }
    const self = this;
    this.socket = new WebSocket(`wss://${url}`);
    this.socket.onopen = (e) => { // 连接建立时触发
      if (this.isSignSuccess) {
        this.OnRecognitionStart();
        this.isSignSuccess = true;
      }
    };
    this.socket.onmessage = (e) => { // 连接建立时触发
      const response = JSON.parse(e.data);  
      if (response.code !== 0) {
        this.OnError(response.message);
        self.socket.close();
        return;
      } else {
        if (!this.isSignSuccess) {
          this.OnRecognitionStart(response);
          this.isSignSuccess = true;
        }
        if (response.final === 1) {
          this.isRecognizeComplete = true;
          this.OnRecognitionComplete(response);
          return;
        }
        if (response.result) {
          if (response.result.slice_type === 0) {
            this.OnSentenceBegin(response);
            this.isSentenceBegin = true;
          } else if (response.result.slice_type === 2) {
            if (!this.isSentenceBegin) {
              this.OnSentenceBegin(response);
            }
            this.OnSentenceEnd(response);
          } else {
            this.OnRecognitionResultChange(response);
          }
        }
      }
    };
    this.socket.onerror = (e) => { // 通信发生错误时触发
      this.socket.close();
      this.OnError(e);
    }
    this.socket.onclose = (event) => {
      if (!this.isRecognizeComplete) {
        this.OnError(event.reason);
      }
    }
  }
  // 发送数据
  write(data) {
    if (!this.socket || this.socket.readyState !== 1) {
      this.OnError('连接未建立，请稍后发送数据！')
      return
    }
    this.socket.send(data);
  };
  // 开始识别的时候
  OnRecognitionStart(res) {

  }
  // 一句话开始的时候
  OnSentenceBegin(res) {

  }
  // 识别结果发生变化的时候
  OnRecognitionResultChange() {

  }
  // 一句话结束的时候
  OnSentenceEnd() {

  }
  // 识别结束的时候
  OnRecognitionComplete() {

  }
  // 识别失败
  OnError() {

  }
}
global.SpeechRecognizer = SpeechRecognizer;
