'use strict';
// LTTB (Largest Triangle Three Buckets) decimation — O(n).
// Runs off-main-thread to avoid blocking the render loop.
function lttb(t, v, threshold) {
  const len = t.length;
  if (len <= threshold) {
    // Copy to new arrays so we can transfer them back without detaching the input.
    return { t: new Float64Array(t), v: new Float64Array(v) };
  }
  const outT = new Float64Array(threshold);
  const outV = new Float64Array(threshold);
  outT[0] = t[0]; outV[0] = v[0];
  outT[threshold - 1] = t[len - 1]; outV[threshold - 1] = v[len - 1];
  const every = (len - 2) / (threshold - 2);
  let a = 0;
  for (let i = 0; i < threshold - 2; i++) {
    const avgS = Math.floor((i + 1) * every) + 1;
    const avgE = Math.min(Math.floor((i + 2) * every) + 1, len);
    let avgT = 0, avgV = 0, n = 0;
    for (let j = avgS; j < avgE; j++) { avgT += t[j]; avgV += v[j]; n++; }
    if (n) { avgT /= n; avgV /= n; }
    const rS = Math.floor(i * every) + 1;
    const rE = Math.min(Math.floor((i + 1) * every) + 1, len);
    let maxA = -1, next = rS;
    const aT = t[a], aV = v[a];
    for (let j = rS; j < rE; j++) {
      const area = Math.abs((aT - avgT) * (v[j] - aV) - (aT - t[j]) * (avgV - aV));
      if (area > maxA) { maxA = area; next = j; }
    }
    outT[i + 1] = t[next]; outV[i + 1] = v[next]; a = next;
  }
  return { t: outT, v: outV };
}

self.onmessage = function({ data: { id, t, v, threshold } }) {
  const result = lttb(t, v, threshold);
  // Transfer the output buffers back to the main thread zero-copy.
  self.postMessage({ id, t: result.t, v: result.v }, [result.t.buffer, result.v.buffer]);
};
