#pragma once
#include <juce_audio_processors/juce_audio_processors.h>
#include "CompressorDSP.h"

class SaftpumpeProcessor : public juce::AudioProcessor {
public:
    SaftpumpeProcessor();
    ~SaftpumpeProcessor() override;

    void prepareToPlay(double sampleRate, int samplesPerBlock) override;
    void releaseResources() override;

    void processBlock(juce::AudioBuffer<float>&, juce::MidiBuffer&) override;

    juce::AudioProcessorEditor* createEditor() override;
    bool hasEditor() const override { return true; }

    const juce::String getName() const override { return JucePlugin_Name; }

    bool acceptsMidi() const override { return false; }
    bool producesMidi() const override { return false; }
    bool isMidiEffect() const override { return false; }
    double getTailLengthSeconds() const override { return 0.0; }

    int getNumPrograms() override { return 1; }
    int getCurrentProgram() override { return 0; }
    void setCurrentProgram(int) override {}
    const juce::String getProgramName(int) override { return {}; }
    void changeProgramName(int, const juce::String&) override {}

    void getStateInformation(juce::MemoryBlock& destData) override;
    void setStateInformation(const void* data, int sizeInBytes) override;

    static constexpr const char* thresholdID = "threshold";
    static constexpr const char* ratioID = "ratio";
    static constexpr const char* attackID = "attack";
    static constexpr const char* releaseID = "release";
    static constexpr const char* kneeID = "knee";
    static constexpr const char* makeupID = "makeup";
    static constexpr const char* mixID = "mix";
    static constexpr const char* autoReleaseID = "autoRelease";

    juce::AudioProcessorValueTreeState parameters;

    float getGainReductionMeter() const { return currentGainReduction; }
    float getInputLevel() const { return currentInputLevel; }
    float getOutputLevel() const { return currentOutputLevel; }

    static constexpr int scopeSize = 512;
    std::array<float, scopeSize> inputScope{};
    std::array<float, scopeSize> outputScope{};
    int scopeIndex = 0;

private:
    CompressorDSP compressorL;
    CompressorDSP compressorR;

    float currentGainReduction = 0.0f;
    float currentInputLevel = 0.0f;
    float currentOutputLevel = 0.0f;

    void updateCompressorParams();

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SaftpumpeProcessor)
};
