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

  Audacity: A Digital Audio Editor

  StatefulPerTrackEffect.h

  Dominic Mazzoni
  Vaughan Johnson

  Paul Licameli split from PerTrackEffect.h

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

#ifndef __AUDACITY_STATEFUL_PER_TRACK_EFFECT__
#define __AUDACITY_STATEFUL_PER_TRACK_EFFECT__

#include "PerTrackEffect.h" // to inherit
#include "StatefulEffectBase.h" // to inherit

//! Subclass of PerTrackEffect, to be eliminated after all of its subclasses
//! are rewritten to be stateless
class EFFECTS_API StatefulPerTrackEffect :
    public StatefulEffectBase,
    public PerTrackEffect
{
public:

   //! Implemented with call-throughs to the
   //! StatefulPerTrackEffect virtual functions
   class EFFECTS_API Instance :
       public StatefulEffectBase::Instance,
       public PerTrackEffect::Instance
   {
   public:
      explicit Instance(StatefulPerTrackEffect &effect)
         : StatefulEffectBase::Instance{ effect }
         , PerTrackEffect::Instance{ effect }
      {}
      ~Instance() override;
      bool ProcessInitialize(EffectSettings &settings, double sampleRate,
         ChannelNames chanMap) override;
      bool ProcessFinalize() noexcept override;
      size_t ProcessBlock(EffectSettings &settings,
         const float *const *inBlock, float *const *outBlock, size_t blockLen)
      override;

   protected:
      StatefulPerTrackEffect &GetEffect() const
      {
         // Tolerate const_cast in this class while it sun-sets
         return static_cast<StatefulPerTrackEffect &>(
            const_cast<PerTrackEffect &>(mProcessor));
      }
   };

   ~StatefulPerTrackEffect() override;

   std::shared_ptr<EffectInstance> MakeInstance() const override;

   size_t SetBlockSize(size_t maxBlockSize) override;
   size_t GetBlockSize() const override;

   /*!
    @copydoc PerTrackEffect::Instance::ProcessInitialize()
    */
   bool ProcessInitialize(EffectSettings &settings, double sampleRate,
      ChannelNames chanMap = nullptr) override;

   /*!
    @copydoc PerTrackEffect::Instance::ProcessFinalize()
    */
   bool ProcessFinalize() noexcept override;

   /*!
    @copydoc PerTrackEffect::Instance::ProcessBlock()
    */
   virtual size_t ProcessBlock(EffectSettings &settings,
      const float *const *inBlock, float *const *outBlock, size_t blockLen) = 0;

private:
   bool Process(EffectInstance &instance, EffectSettings &settings) final;

   size_t mBlockSize{};
};

#endif
