// SPDX-License-Identifier: Unlicense

#include "api.h"

#ifdef SHR3D_SFX_CORE_EXTENSION_V2

#include <stdio.h>

static constexpr f32 default_pan = 0.5f;

struct PanInstance final : SfxCoreExtensionV2Instance
{
  f32 pan = default_pan;

  ProcessBlockResult processBlock(f32** inBlock, f32** /*outBlock*/, const i32 blockSize) override
  {
    const f32 angle = pan * (PI_ / 2.0f);
    const f32 volumeLeft = cosf(angle);
    const f32 volumeRight = sinf(angle);

    for (i32 i = 0; i < blockSize; ++i)
    {
      inBlock[0][i] *= volumeLeft;
      inBlock[1][i] *= volumeRight;
    }
    return ProcessBlockResult::ProcessedInInBlock;
  }

  f32 getParameter(const i32 index) const override
  {
    switch (index)
    {
    case 0:
      return pan;
    default:
      unreachable();
    }
  }

  void setParameter(const i32 index, const f32 value) override
  {
    switch (index)
    {
    case 0:
      pan = value;
      break;
    default:
      unreachable();
    }
  }

  void getParameterDisplay(const i32 index, char* text) override
  {
    switch (index)
    {
    case 0:
      sprintf(text, "%8.2f", pan * 2.0f - 1.0f);
      break;
    default:
      unreachable();
    }
  }

  void resetParameter(const i32 index) override
  {
    switch (index)
    {
    case 0:
      pan = default_pan;
      break;
    default:
      unreachable();
    }
  }
};

static struct Pan_ final : SfxCoreExtensionV2Base
{
  Pan_()
  {
    RegisterSfxCoreExtensionV2(u8"Pan", this);
  }

  i32 getParameterCount() const override
  {
    return 1;
  }

  const char8_t* getParameterLabel(const i32 index) override
  {
    switch (index)
    {
    case 0:
      return u8"l/r";
    default:
      unreachable();
    }
  }

  const char8_t* getParameterName(const i32 index) override
  {
    switch (index)
    {
    case 0:
      return u8"Pan";
    default:
      unreachable();
    }
  }

  SfxCoreExtensionV2Instance* getInstance(const i32 instance) override
  {
    static SfxCoreExtensionV2Instance* instances[ExtensionV2MaxInstanceCount];
    assert(instance < ARRAY_SIZE(instances));

    if (instances[instance] == nullptr)
      instances[instance] = new PanInstance;

    return instances[instance];
  }
} pan_;

#endif // SHR3D_SFX_CORE_EXTENSION_V2
