var gWASM;  // globální proměnná + elementy stránky
const Outs   = document.getElementById('stdout');
const Btnt   = document.getElementById('buttonTest');
const Canvas = document.getElementById('canvas');
// async/await z příkladu na webu
window.onload = async function() {
  Btnt.disabled = true;
  Outs.value = 'Compiling ...¨\n';        // presets
  // Build WebAssembly instance - WebAssembly.instantiateStreaming problem
  const memory = new WebAssembly.Memory({ initial: 4 });
  const importObject = {
    env: { memory },      // nutné pro práci a pamětí
    imports: {            // importované funkce do wasm
      printout : (ptr, len) => {
        // pohled do paměti - ptr je vlastně číslo
        const view = new Uint8Array (memory.buffer, ptr, len);
        const utf8decoder = new TextDecoder();
        Outs.value += utf8decoder.decode(view); // to String
      },
      memoryGrow :  (len) => {
        console.log ('Growing the memory by ' + len.toString() + '. 64K blocks');
        memory.grow (len); // patrně to jde volat přímo z C/C++ kódu, ale tohle funguje
      },
      drawPoints : (px, py, len, pj, jl) => {
        const xview = new Float32Array (memory.buffer, px, len);
        const yview = new Float32Array (memory.buffer, py, len);
        const view  = new Uint8Array   (memory.buffer, pj, jl);
        const utf8decoder = new TextDecoder();
        const obj = JSON.parse (utf8decoder.decode(view));
        // console.log (obj);
        polyLine (xview, yview, len, obj);
      },
    },
  };
  const response = await fetch('./module.wasm');
  const bytes    = await response.arrayBuffer();
  const module   = await WebAssembly.instantiate(bytes, importObject);
  gWASM = {
    asm : module.instance.exports,
    mem : memory,
  };
  gWASM.asm.init(memory.buffer.byteLength);
  Btnt.onclick = () => {
    Outs.value = '';
    const expression = document.getElementById('input').value;
    // console.log(expression);
    stringToModule (expression, gWASM.asm.compute);
  };
  Outs.value = 'Module compiled - [insert formula and] press button Submit\n';
  Btnt.disabled = false;
  // console.log (gWASM);
  window.addEventListener('resize', resizeCanvas, false);
  resizeCanvas();
  getFile ('test.txt');
  Splash ();
};
function stringToModule (str, mfunc) {
  const utf8EncodeText = new TextEncoder();
  const bytes = utf8EncodeText.encode(str);
  // alokovat pamet v modulu je nutne, aby bylo kam kopirovat
  const cArrayPointer = gWASM.asm.cAlloc(bytes.length);
  if (!cArrayPointer) return;
  const cArray = new Uint8Array(gWASM.mem.buffer, cArrayPointer, bytes.length);
  cArray.set(bytes);              // naplnit dekodovanym stringem
  mfunc (cArrayPointer, cArray.length);
}
function resizeCanvas () {
  const width   = canvas.clientWidth;
  const height  = canvas.clientHeight;
  canvas.width  = width;
  canvas.height = height;
  // console.log (width, height);
  gWASM.asm.resizeCanvas (width, height);
}
function drawLine (ctx, line, x, y) {
  ctx.beginPath();
  ctx.moveTo(line.b[0], line.b[1]);
  ctx.lineTo(line.e[0], line.e[1]);
  ctx.lineWidth   = line.w;
  ctx.strokeStyle = line.color;
  if (line.lbl) {
    //console.log (line.lbl);
    ctx.fillStyle = line.color;
    ctx.fillText (line.lbl, line.b[0] + x, line.b[1] - y);
  }
  ctx.stroke();
}
const colors = ['#00ff00', '#ff0000', '#00ffff', '#ff00ff'];
var colorIndex = 0;
function polyLine (ax, ay, len, obj) {
  // console.log (ax, ay);
  const ctx = canvas.getContext("2d");
  if (obj.name === "axes") {
    colorIndex = 0;
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.font = '16px serif';
    ctx.textAlign = 'left';
    drawLine (ctx, obj.x, 0, 0);
    drawLine (ctx, obj.y, 0, 0);
    const ndotsx = obj.xdots.length;
    for (let n=0; n<ndotsx; n++) { drawLine (ctx, obj.xdots[n],  0, 5); }
    const ndotsy = obj.ydots.length;
    for (let n=0; n<ndotsy; n++) { drawLine (ctx, obj.ydots[n], 10, 0); }
  }
  ctx.beginPath();
  ctx.moveTo(ax[0], ay[0]);
  for (let n=1; n<len; n++) {
    ctx.lineTo(ax[n], ay[n]);
  }
  ctx.lineWidth   = 3;
  ctx.strokeStyle = colors [colorIndex++ % 4];
  ctx.stroke();
}
async function getFile (name) {
  const response = await fetch (name);
  if (!response.ok) return;
  const bytes    = await response.arrayBuffer();
  const array    = new Uint8Array(bytes);
  const decoder  = new TextDecoder();
  document.getElementById('input').value = decoder.decode(bytes);
}
function Splash () {
  const content = Canvas.getContext('2d');
  content.font = '96px serif';
  content.fillStyle = '#00FF00';
  content.textAlign = 'center';
  content.fillText ('Graphic calculator', Canvas.width / 2, Canvas.height / 2);
}