text: #pragma once
  
  #include <juce_audio_processors/juce_audio_processors.h>
  
  #include <unordered_map>
  
  #include "../audio_engine/ReverbController.h"
  #include "../concurrentqueue/concurrentqueue.h"
  
  //==============================================================================
  class AudioPluginAudioProcessor : public juce::AudioProcessor, private juce::AudioProcessorValueTreeState::Listener {
  public:
      //==============================================================================
      AudioPluginAudioProcessor();
      ~AudioPluginAudioProcessor() override;
  
      //==============================================================================
      void prepareToPlay(double sampleRate, int samplesPerBlock) override;
      void releaseResources() override;
      void parameterChanged(const juce::String& parameterID, float newValue) override;
  
      bool isBusesLayoutSupported(const BusesLayout& layouts) const override;
  
      void processBlock(juce::AudioBuffer<float>&, juce::MidiBuffer&) override;
  
      //==============================================================================
      juce::AudioProcessorEditor* createEditor() override;
      bool hasEditor() const override;
  
      //==============================================================================
      const juce::String getName() const override;
  
      bool acceptsMidi() const override;
      bool producesMidi() const override;
      bool isMidiEffect() const override;
      double getTailLengthSeconds() const override;
  
      //==============================================================================
      int getNumPrograms() override;
      int getCurrentProgram() override;
      void setCurrentProgram(int index) override;
      const juce::String getProgramName(int index) override;
      void changeProgramName(int index, const juce::String& newName) override;
  
      //==============================================================================
      void getStateInformation(juce::MemoryBlock& destData) override;
      void setStateInformation(const void* data, int sizeInBytes) override;
  
      juce::AudioProcessorValueTreeState treeState;
  
      std::unordered_map<juce::String, Parameter> map;
      struct Message {
          float newNormalisedValue;
          float newScaledValue;
          Parameter param;
      };
  
  private:
      CloudSeed::ReverbController reverb;
  
      moodycamel::ConcurrentQueue<Message> queue;
  
      //==============================================================================
      JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(AudioPluginAudioProcessor)
  };
  