/**
 * Copyright FunASR (https://github.com/alibaba-damo-academy/FunASR). All Rights
 * Reserved. MIT License  (https://opensource.org/licenses/MIT)
 */
/* 2022-2023 by zhaoming,mali aihealthx.com */


// 连接; 定义socket连接类对象与语音对象
var wsconnecter = new WebSocketConnectMethod({ msgHandle: getJsonMessage, stateHandle: getConnState });
var audioBlob;
var isfilemode = true;  // if it is in file mode
// 录音; 定义录音对象,wav格式
var rec = Recorder({
  type: "pcm",
  bitRate: 16,
  sampleRate: 16000,
  onProcess: recProcess
});

var sampleBuf = new Int16Array();

var rec_text = "";  // for online rec asr result
var offline_text = ""; // for offline rec asr result


var file_ext = "";
var file_sample_rate = 16000; //for wav file sample rate
var file_data_array;  // array to save file data
var totalsend = 0;

addresschange();
function addresschange() {
  var Uri = 'ws://192.168.0.232:10095';
  Uri = Uri.replace(/wss/g, "https");
  // window.open(Uri, '_blank');
}





var readWavInfo = function (bytes) {
  //读取wav文件头，统一成44字节的头
  if (bytes.byteLength < 44) {
    return null;
  };
  var wavView = bytes;
  var eq = function (p, s) {
    for (var i = 0; i < s.length; i++) {
      if (wavView[p + i] != s.charCodeAt(i)) {
        return false;
      };
    };
    return true;
  };

  if (eq(0, "RIFF") && eq(8, "WAVEfmt ")) {

    var numCh = wavView[22];
    if (wavView[20] == 1 && (numCh == 1 || numCh == 2)) {//raw pcm 单或双声道
      var sampleRate = wavView[24] + (wavView[25] << 8) + (wavView[26] << 16) + (wavView[27] << 24);
      var bitRate = wavView[34] + (wavView[35] << 8);
      var heads = [wavView.subarray(0, 12)], headSize = 12;//head只保留必要的块
      //搜索data块的位置
      var dataPos = 0; // 44 或有更多块
      for (var i = 12, iL = wavView.length - 8; i < iL;) {
        if (wavView[i] == 100 && wavView[i + 1] == 97 && wavView[i + 2] == 116 && wavView[i + 3] == 97) {//eq(i,"data")
          heads.push(wavView.subarray(i, i + 8));
          headSize += 8;
          dataPos = i + 8; break;
        }
        var i0 = i;
        i += 4;
        i += 4 + wavView[i] + (wavView[i + 1] << 8) + (wavView[i + 2] << 16) + (wavView[i + 3] << 24);
        if (i0 == 12) {//fmt
          heads.push(wavView.subarray(i0, i));
          headSize += i - i0;
        }
      }
      if (dataPos) {
        var wavHead = new Uint8Array(headSize);
        for (var i = 0, n = 0; i < heads.length; i++) {
          wavHead.set(heads[i], n); n += heads[i].length;
        }
        return {
          sampleRate: sampleRate
          , bitRate: bitRate
          , numChannels: numCh
          , wavHead44: wavHead
          , dataPos: dataPos
        };
      };
    };
  };
  return null;
};

function upfileOnchange(files) {
  this.files = [files];
  var len = this.files.length;
  for (let i = 0; i < len; i++) {
    let fileAudio = new FileReader();
    fileAudio.readAsArrayBuffer(this.files[i]);
    file_ext = this.files[i].name.split('.').pop().toLowerCase();
    var audioblob;
    fileAudio.onload = function () {
      audioblob = fileAudio.result;
      file_data_array = audioblob;
    }

    fileAudio.onerror = function (e) {
      console.log('error' + e);
    }
  }
  // for wav file, we  get the sample rate
  if (file_ext == "wav") {
    for (let i = 0; i < len; i++) {
      let fileAudio = new FileReader();
      fileAudio.readAsArrayBuffer(this.files[i]);
      fileAudio.onload = function () {
        audioblob = new Uint8Array(fileAudio.result);

        var info = readWavInfo(audioblob);
        file_sample_rate = info.sampleRate;
      }
    }
  }

}

function play_file() {
  var audioblob = new Blob([new Uint8Array(file_data_array)], { type: "audio/wav" });
  var audio_record = document.getElementById('audio_record');
  audio_record.src = (window.URL || webkitURL).createObjectURL(audioblob);
  audio_record.controls = true;
}

function start_file_send() {
  sampleBuf = new Uint8Array(file_data_array);
  var chunk_size = 960; // for asr chunk_size [5, 10, 5]
  while (sampleBuf.length >= chunk_size) {
    sendBuf = sampleBuf.slice(0, chunk_size);
    totalsend = totalsend + sampleBuf.length;
    sampleBuf = sampleBuf.slice(chunk_size, sampleBuf.length);
    wsconnecter.wsSend(sendBuf);
  }
  stop();
}

function stop() {
  var chunk_size = new Array(5, 10, 5);
  var request = {
    "chunk_size": chunk_size,
    "wav_name": "h5",
    "is_speaking": false,
    "chunk_interval": 10,
    "mode": getAsrMode(),
  };
  if (sampleBuf.length > 0) {
    wsconnecter.wsSend(sampleBuf);
    sampleBuf = new Int16Array();
  }
  wsconnecter.wsSend(JSON.stringify(request));
  // 控件状态更新
  isRec = false;
  if (isfilemode == false) {
    //wait 3s for asr result
    setTimeout(function () {
      wsconnecter.wsStop();
    }, 3000);
    rec.stop(function (blob, duration) {
      var audioBlob = Recorder.pcm2wav(data = { sampleRate: 16000, bitRate: 16, blob: blob },
        function (theblob, duration) {
          console.log(theblob);
          var audio_record = document.getElementById('audio_record');
          audio_record.src = (window.URL || webkitURL).createObjectURL(theblob);
          audio_record.controls = true;
        }, function (msg) {
          console.log(msg);
        }
      );



    }, function (errMsg) {
      console.log("errMsg: " + errMsg);
    });
  }
  // 停止连接
}

function getAsrMode() {
  return 'offline';
}
function getHotwords() {
  return null
}


function handleWithTimestamp(tmptext, tmptime) {

  if (tmptime == null || tmptime == "undefined" || tmptext.length <= 0) {
    return tmptext;
  }
  tmptext = tmptext.replace(/。|？|，|、|\?|\.|\ /g, ","); // in case there are a lot of "。"
  var words = tmptext.split(",");  // split to chinese sentence or english words
  var jsontime = JSON.parse(tmptime); //JSON.parse(tmptime.replace(/\]\]\[\[/g, "],[")); // in case there are a lot segments by VAD
  var char_index = 0; // index for timestamp
  var text_withtime = "";
  for (var i = 0; i < words.length; i++) {
    if (words[i] == "undefined" || words[i].length <= 0) {
      continue;
    }
    if (/^[a-zA-Z]+$/.test(words[i])) {   // if it is english
      text_withtime = text_withtime + jsontime[char_index][0] / 1000 + ":" + words[i] + "\n";
      char_index = char_index + 1;  //for english, timestamp unit is about a word
    }
    else {
      text_withtime = text_withtime + jsontime[char_index][0] / 1000 + ":" + words[i] + "\n";
      char_index = char_index + words[i].length; //for chinese, timestamp unit is about a char
    }
  }
  return text_withtime;


}
// 语音识别结果; 对jsonMsg数据解析,将识别结果附加到编辑框中
function getJsonMessage(jsonMsg) {
  var rectxt = "" + JSON.parse(jsonMsg.data)['text'];
  var asrmodel = JSON.parse(jsonMsg.data)['mode'];
  var is_final = JSON.parse(jsonMsg.data)['is_final'];
  var timestamp = JSON.parse(jsonMsg.data)['timestamp'];
  if (asrmodel == "2pass-offline" || asrmodel == "offline") {
    offline_text = offline_text + handleWithTimestamp(rectxt, timestamp); //rectxt; //.replace(/ +/g,"");
    rec_text = offline_text;
  } else {
    rec_text = rec_text + rectxt;
  }
  videoText = rec_text;
  if (is_final == true) {
    play_file();
    wsconnecter.wsStop();
    btnConnect.disabled = false;
  }
}

// 连接状态响应
function getConnState(connState) {
  if (connState === 0) start_file_send();
}

// 识别启动、停止、清空操作
function start() {
  var ret = wsconnecter.wsStart();//启动连接
  return ret == 1 ? 1 : 0;
}

function recProcess(buffer, powerLevel, bufferDuration, bufferSampleRate, newBufferIdx, asyncEnd) {
  if (isRec === true) {
    var data_48k = buffer[buffer.length - 1];
    var array_48k = new Array(data_48k);
    var data_16k = Recorder.SampleData(array_48k, bufferSampleRate, 16000).data;
    sampleBuf = Int16Array.from([...sampleBuf, ...data_16k]);
    var chunk_size = 960; // for asr chunk_size [5, 10, 5]
    while (sampleBuf.length >= chunk_size) {
      sendBuf = sampleBuf.slice(0, chunk_size);
      sampleBuf = sampleBuf.slice(chunk_size, sampleBuf.length);
      wsconnecter.wsSend(sendBuf);
    }
  }
}

function getUseITN() {
  return false;
}
