/**
References
https://developer.mozilla.org/en-US/docs/Web/API/FileList
https://developer.mozilla.org/en-US/docs/Web/API/FileReader
https://javascript.info/arraybuffer-binary-arrays
https://developer.mozilla.org/zh-CN/docs/Web/API/WebSocket
https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send
*/

var socket;

const serverIpInput = document.getElementById('server-ip');
const serverPortInput = document.getElementById('server-port');

const connectBtn = document.getElementById('connect');
const uploadBtn = document.getElementById('file');

function initWebSocket() {
  let protocol = 'ws://';
  if (window.location.protocol == 'https:') {
    protocol = 'wss://'
  }
  let server_ip = serverIpInput.value;
  let server_port = serverPortInput.value;
  console.log('protocol: ', protocol);
  console.log('server_ip: ', server_ip);
  console.log('server_port: ', server_port);


  let uri = protocol + server_ip + ':' + server_port;
  console.log('uri', uri);
  socket = new WebSocket(uri);

  // Connection opened
  socket.addEventListener('open', function(event) {
    console.log('connected');
    uploadBtn.disabled = false;
    connectBtn.disabled = true;
    connectBtn.innerHTML = 'Connected!';
  });

  // Connection closed
  socket.addEventListener('close', function(event) {
    console.log('disconnected');
    uploadBtn.disabled = true;
    connectBtn.disabled = false;
    connectBtn.innerHTML = 'Click me to connect!';
  });

  // Listen for messages
  socket.addEventListener('message', function(event) {
    console.log('Received message: ', event.data);

    document.getElementById('results').value = event.data;
    socket.send('Done');
    console.log('Sent Done');
    socket.close();
  });
}

window.onload = (event) => {
  console.log('page is fully loaded');
  console.log('protocol', window.location.protocol);
  console.log('port', window.location.port);
  if (window.location.protocol == 'https:') {
    document.getElementById('ws-protocol').textContent = 'wss://';
  }
  serverIpInput.value = window.location.hostname;
  serverPortInput.value = window.location.port;
};

connectBtn.onclick = function() {
  initWebSocket();
};

function send_header(n) {
  const header = new ArrayBuffer(8);
  // assume the uploaded wave is 16000 Hz
  new DataView(header).setInt32(0, 16000, true /* littleEndian */);
  new DataView(header).setInt32(4, n, true /* littleEndian */);
  socket.send(new Int32Array(header, 0, 2));
}

function onFileChange() {
  var files = document.getElementById('file').files;

  if (files.length == 0) {
    console.log('No file selected');
    return;
  }

  console.log('files: ' + files);

  const file = files[0];
  console.log(file);
  console.log('file.name ' + file.name);
  console.log('file.type ' + file.type);
  console.log('file.size ' + file.size);

  let audioCtx = new AudioContext({sampleRate: 16000});

  let reader = new FileReader();
  reader.onload = function() {
    console.log('reading file!');
    audioCtx.decodeAudioData(reader.result, decodedDone);
  };

  function decodedDone(decoded) {
    let typedArray = new Float32Array(decoded.length);
    let float32_samples = decoded.getChannelData(0);
    let buf = float32_samples.buffer

    // Send 1024 audio samples per request.
    //
    // It has two purposes:
    //  (1) Simulate streaming
    //  (2) There is a limit on the number of bytes in the payload that can be
    //      sent by websocket, which is 1MB, I think. We can send a large
    //      audio file for decoding in this approach.
    let n = 1024 * 4;  // send this number of bytes per request.
    console.log('buf length, ' + buf.byteLength);
    send_header(buf.byteLength);
    for (let start = 0; start < buf.byteLength; start += n) {
      socket.send(buf.slice(start, start + n));
    }
  }

  reader.readAsArrayBuffer(file);
}

const clearBtn = document.getElementById('clear');
clearBtn.onclick = function() {
  console.log('clicked');
  document.getElementById('results').value = '';
};
