export interface WaveformData {
  peaks: number[];
  duration: number;
  sampleRate: number;
}

export class WaveformAnalyzer {
  /**
   * Generate waveform data from an audio buffer
   * @param audioBuffer - Web Audio API AudioBuffer
   * @param targetWidth - Number of data points to generate (typically canvas width)
   * @returns Normalized waveform data
   */
  static generateWaveformData(audioBuffer: AudioBuffer, targetWidth: number = 800): WaveformData {
    const channelData = audioBuffer.getChannelData(0); // Use first channel (mono or left channel)
    const sampleRate = audioBuffer.sampleRate;
    const duration = audioBuffer.duration;
    
    // Calculate how many samples per pixel
    const samplesPerPixel = Math.floor(channelData.length / targetWidth);
    const peaks: number[] = [];
    
    for (let i = 0; i < targetWidth; i++) {
      const start = i * samplesPerPixel;
      const end = Math.min(start + samplesPerPixel, channelData.length);
      
      // Find the peak (maximum absolute value) in this segment
      let peak = 0;
      for (let j = start; j < end; j++) {
        const sample = Math.abs(channelData[j]);
        if (sample > peak) {
          peak = sample;
        }
      }
      
      peaks.push(peak);
    }
    
    // Normalize peaks to 0-1 range
    const maxPeak = Math.max(...peaks);
    const normalizedPeaks = maxPeak > 0 ? peaks.map(peak => peak / maxPeak) : peaks;
    
    return {
      peaks: normalizedPeaks,
      duration,
      sampleRate
    };
  }
  
  /**
   * Generate waveform data from an audio URL
   * @param audioUrl - URL of the audio file
   * @param targetWidth - Number of data points to generate
   * @returns Promise with waveform data
   */
  static async generateWaveformFromUrl(audioUrl: string, targetWidth: number = 800): Promise<WaveformData> {
    try {
      // Fetch audio data
      const response = await fetch(audioUrl);
      const arrayBuffer = await response.arrayBuffer();
      
      // Create audio context and decode audio data
      const audioContext = new (window.AudioContext || (window as any).webkitAudioContext)();
      const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
      
      // Generate waveform data
      const waveformData = this.generateWaveformData(audioBuffer, targetWidth);
      
      // Close audio context to free resources
      audioContext.close();
      
      return waveformData;
    } catch (error) {
      console.error('Failed to generate waveform from URL:', error);
      throw error;
    }
  }
  
  /**
   * Create a smooth waveform by applying a simple moving average
   * @param peaks - Raw peak data
   * @param smoothingFactor - Higher values = more smoothing (1-10)
   * @returns Smoothed peak data
   */
  static smoothWaveform(peaks: number[], smoothingFactor: number = 3): number[] {
    if (smoothingFactor <= 1) return peaks;
    
    const smoothed: number[] = [];
    const halfWindow = Math.floor(smoothingFactor / 2);
    
    for (let i = 0; i < peaks.length; i++) {
      let sum = 0;
      let count = 0;
      
      for (let j = Math.max(0, i - halfWindow); j <= Math.min(peaks.length - 1, i + halfWindow); j++) {
        sum += peaks[j];
        count++;
      }
      
      smoothed.push(sum / count);
    }
    
    return smoothed;
  }
}