export const DEFAULT_CHUNK_SAMPLES = 2000;

export function getAudioSamples(
  audioData: AudioBuffer,
  options?: {
    /**
     * Number of samples per second
     */
    sampleRate?: number;
    /**
     * Total number of samples read
     */
    chunkSamples?: number;
    /**
     * Total number of samples
     */
    numSamples?: number;
  }
) {
  const leftChannel = audioData.getChannelData(0);
  const rightChannel =
    audioData.numberOfChannels > 1
      ? audioData.getChannelData(1)
      : new Float32Array([...leftChannel]);

  const {
    sampleRate = 15,
    chunkSamples: optionsChunkSamples = audioData.duration
      ? audioData.duration * sampleRate
      : DEFAULT_CHUNK_SAMPLES,
  } = options || {};

  const [chunkSamples, numSamples] = options?.numSamples
    ? [leftChannel.length / options.numSamples, options.numSamples]
    : [
        optionsChunkSamples,
        Math.floor(leftChannel.length / optionsChunkSamples),
      ];

  const samples = new Array(numSamples).fill(0).map((_v, index) => {
    const leftSamples = leftChannel.slice(
      index * chunkSamples,
      (index + 1) * chunkSamples
    );
    const rightSamples = rightChannel.slice(
      index * chunkSamples,
      (index + 1) * chunkSamples
    );
    const leftSum = leftSamples.reduce((acc, v) => acc + v ** 2, 0);
    const rightSum = rightSamples.reduce((acc, v) => acc + v ** 2, 0);
    return Math.sqrt((leftSum + rightSum) / (chunkSamples * 2));
  });

  return samples;
}

export async function decodeAudioData(
  audioUrl: string,
  options?: AudioContextOptions
) {
  const AudioContext =
    typeof window !== 'undefined'
      ? window.AudioContext || (window as any).webkitAudioContext
      : undefined;

  if (!AudioContext) return null;

  const response = await fetch(audioUrl);
  const arrayBuffer = await response.arrayBuffer();

  const audioContext = new AudioContext({ sampleRate: 8000, ...options });
  const audioData = await audioContext.decodeAudioData(arrayBuffer);

  return audioData;
}
