/*!********************************************************************

  Audacity: A Digital Audio Editor

  @file AudioUnitEditor.h

  Dominic Mazzoni
  Leland Lucius

  Paul Licameli split from AudioUnitEffect.cpp

**********************************************************************/

#ifndef __AUDACITY_AUDIO_UNIT_EDITOR__
#define __AUDACITY_AUDIO_UNIT_EDITOR__

#include <AudioToolbox/AudioUnitUtilities.h>
#include <unordered_map>
#include "AudioUnitUtils.h"
#include "../EffectEditor.h"

class AUControl;

class AudioUnitInstance;
class EffectSettings;
class EffectInstance;
class ShuttleGui;

class AudioUnitEditor : public wxEvtHandler, public EffectEditor {
   struct CreateToken{};
public:
   static std::unique_ptr<EffectEditor> Create(
      const EffectUIServices &effect, ShuttleGui &S,
      const wxString &uiType,
      EffectInstance &instance, EffectSettingsAccess &access);

   AudioUnitEditor(CreateToken,
      const EffectUIServices &effect, EffectSettingsAccess &access,
      AudioUnitInstance &instance, AUControl *pControl, bool isGraphical);

   ~AudioUnitEditor() override;

   bool UpdateUI() override;
   bool ValidateUI() override;
   bool IsGraphicalUI() override;

private:
   static void EventListenerCallback(void *inCallbackRefCon,
      void *inObject, const AudioUnitEvent *inEvent,
      UInt64 inEventHostTime, AudioUnitParameterValue inParameterValue);
   void EventListener(const AudioUnitEvent *inEvent,
      AudioUnitParameterValue inParameterValue);
   void OnIdle(wxIdleEvent &evt);
   bool FetchSettingsFromInstance(EffectSettings &settings);
   bool StoreSettingsToInstance(const EffectSettings &settings);

   void Notify();

   using EventListenerPtr =
      AudioUnitCleanup<AUEventListenerRef, AUListenerDispose>;

   EventListenerPtr MakeListener();

   // The lifetime guarantee is assumed to be provided by the instance.
   // See contract of PopulateUI
   AudioUnitInstance &mInstance;
   const EventListenerPtr mEventListenerRef;
   AUControl *const mpControl{};
   std::vector<
      std::pair<AudioUnitParameterID, AudioUnitParameterValue>> mToUpdate;
   const bool mIsGraphical;

   // The map of parameter IDs to their current values
   std::unordered_map<AudioUnitParameterID, AudioUnitParameterValue>
      mParameterValues;
};
#endif
