import decode from '../signal-processing/decodeAudio.js';

export const blue500 = '#455eff';
export const blue400 = '#394ecf';
export const blue300 = '#2b24e5';

interface ChannelPoint {
  hf: number;
  mf: number;
  lmf: number;
  lf: number;
}

const LF_MULTIPLIER = 2;
const LMF_MULTIPLIER = 1.5;
const MF_MULTIPLIER = 1;
const HF_MULTIPLIER = 0.75;

const generateSampleWaveformFromBuffer = async (buffer: Buffer) => {
  const svgHeight = 98;
  const ampMultiplier = svgHeight / 2;

  // TODO this should use a lower rate, but the bin cutoffs need to be adjusted
  const audioBuffer = await decode(buffer, { sampleRate: 4000 });
  const { channelData } = audioBuffer;

  let batchMax = 0;
  let batchMin = 0;
  const resolutionDivider = Math.round(channelData[0].length / 500);
  const waveformPoints = [[], []];
  for (let i = 0; i < channelData[0].length; i++) {
    if (i % 2048 === 0) {
      await pause();
    }

    let monoAvg = 0.0;
    for (let j = 0; j < channelData.length; j++) {
      monoAvg += channelData[j][i];
    }
    monoAvg /= channelData.length;

    batchMax = Math.max(batchMax, monoAvg);
    batchMin = Math.min(batchMin, monoAvg);

    if (i % resolutionDivider === 0) {
      waveformPoints[0].push(batchMax * ampMultiplier);
      waveformPoints[1].push(batchMin * ampMultiplier);
      batchMax = 0;
      batchMin = 0;
    }
  }

  const baseline = svgHeight / 2;
  let pathElements = `M0,${baseline} L1,${baseline} `;

  waveformPoints[0].forEach((point, i) => {
    pathElements += `L${i},${Math.round(svgHeight / 2 - point)} `;
  });

  waveformPoints[1].reverse().forEach((point, i) => {
    const reverseI = waveformPoints[0].length - i;
    pathElements += `L${reverseI},${Math.round(svgHeight / 2 - point)} `;
  });

  let svgString = `<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 500 98" preserveAspectRatio="none">`;
  svgString += `<path d="${pathElements}" style="stroke: ${blue300}; fill: ${blue300};"></path>`;
  svgString += '</svg>';

  return svgString;
};

const pause = () => new Promise((resolve) => setTimeout(resolve, 0));

export default generateSampleWaveformFromBuffer;
