#pragma once
#include "buffer.h"

class BiQuadFilter final {
public:
  enum class Mode {
    LOWPASS,
    HIGHPASS,
    BANDPASS,
    NOTCH,
    ALLPASS,
    EQ_BAND,
    LOW_SHELF,
    HIGH_SHELF,
    BYPASS,
  };

  BiQuadFilter(int sampleRate);

  void processBuffer(BufferF32 frequencyInput, BufferF32 dbGainInput,
                     BufferF32 qInput, BufferF32 input, BufferF32 output,
                     Mode mode);

  void processBufferConstant(float frequency, float dbGain, float q,
                             BufferF32 input, BufferF32 output, Mode mode);

  void reset();

private:
  const int sampleRate;
  const float nyquistLimit;
  const float w0Coef;

  float xn2, xn1, yn2, yn1;
};

class FilterChain final {
public:
  FilterChain(int sampleRate, int channelCount, int filterCount);

  void processBuffer(BufferF32 buf);

  int getFilterCount() const;

  BiQuadFilter::Mode getMode(int idx) const;
  void setMode(int idx, BiQuadFilter::Mode mode);

  float getFrequency(int idx) const;
  void setFrequency(int idx, float frequency);

  float getGain(int idx) const;
  void setGain(int idx, float dbGain);

  float getQ(int idx) const;
  void setQ(int idx, float q);

private:
  const int channelCount;

  struct FilterConfig {
    float frequency;
    float dbGain;
    float q;
    uint32_t mode;
    std::vector<BiQuadFilter> filters;
  };

  std::vector<FilterConfig> filterConfigs;
};