/// <reference lib="webworker" />

import { aggregatePcmPeaks } from './peak-aggregation';
import type {
  WaveformPcmInput,
  WaveformWorkerAggregateRequest,
  WaveformWorkerErrorResponse,
  WaveformWorkerProgressResponse,
  WaveformWorkerResultResponse,
} from './waveform.types';

const workerScope = self as DedicatedWorkerGlobalScope;

workerScope.addEventListener(
  'message',
  (event: MessageEvent<WaveformWorkerAggregateRequest>) => {
    const request = event.data;
    if (
      request?.type !== 'aggregate' ||
      !Number.isSafeInteger(request.requestId)
    ) {
      return;
    }

    try {
      const input = parseInput(request);
      const peaks = aggregatePcmPeaks(input, {
        bucketCount: request.bucketCount,
        ...(request.maxSamples === undefined
          ? {}
          : { maxSamples: request.maxSamples }),
        onProgress: (progress) => {
          const response: WaveformWorkerProgressResponse = {
            type: 'progress',
            requestId: request.requestId,
            progress,
          };
          workerScope.postMessage(response);
        },
      });
      const response: WaveformWorkerResultResponse = {
        type: 'result',
        requestId: request.requestId,
        peaks,
      };
      workerScope.postMessage(response, [
        peaks.minimum.buffer,
        peaks.maximum.buffer,
        peaks.rms.buffer,
      ]);
    } catch (error) {
      const response: WaveformWorkerErrorResponse = {
        type: 'error',
        requestId: request.requestId,
        error: {
          name: error instanceof Error ? error.name : 'Error',
          message:
            error instanceof Error
              ? error.message
              : 'Unknown waveform aggregation error',
        },
      };
      workerScope.postMessage(response);
    }
  }
);

function parseInput(request: WaveformWorkerAggregateRequest): WaveformPcmInput {
  if (request.input.container === 'wav') {
    return {
      container: 'wav',
      data: request.input.data,
    };
  }
  if (
    request.input.container !== 'raw' ||
    request.input.encoding === undefined ||
    request.input.sampleRate === undefined
  ) {
    throw new TypeError('Waveform worker received invalid PCM settings');
  }
  return {
    container: 'raw',
    data: request.input.data,
    encoding: request.input.encoding,
    sampleRate: request.input.sampleRate,
  };
}
