import type { AudioProcessor, ProcessorCategory } from "./AudioProcessor";

export class Waveshaper implements AudioProcessor {
  getName(): string {
    return "Waveshaper";
  }

  getDescription(): string {
    return "Transfer function distortion with various curve shapes";
  }

  getCategory(): ProcessorCategory {
    return 'Distortion';
  }

  async process(
    leftChannel: Float32Array,
    rightChannel: Float32Array
  ): Promise<[Float32Array, Float32Array]> {
    const shapeType = Math.floor(Math.random() * 4);
    const drive = 1 + Math.random() * 4;
    const mix = 0.5 + Math.random() * 0.5;

    const newLeft = new Float32Array(leftChannel.length);
    const newRight = new Float32Array(rightChannel.length);

    for (let i = 0; i < leftChannel.length; i++) {
      const wetL = this.applyShape(leftChannel[i] * drive, shapeType);
      const wetR = this.applyShape(rightChannel[i] * drive, shapeType);

      newLeft[i] = leftChannel[i] * (1 - mix) + wetL * mix;
      newRight[i] = rightChannel[i] * (1 - mix) + wetR * mix;
    }

    return [newLeft, newRight];
  }

  private applyShape(x: number, shapeType: number): number {
    switch (shapeType) {
      case 0:
        return Math.tanh(x);

      case 1:
        return x / (1 + Math.abs(x));

      case 2: {
        const clipped = Math.max(-1, Math.min(1, x));
        return clipped - (clipped * clipped * clipped) / 3;
      }

      case 3: {
        if (x > 1) return 1;
        if (x < -1) return -1;
        return 1.5 * x - 0.5 * x * x * x;
      }

      default:
        return x;
    }
  }
}
