// SPDX-License-Identifier: Unlicense

#include "api.h"

#ifdef SHR3D_SFX_CORE_EXTENSION_V2

#include "../../global.h"
#include "../../nuklear.h"

#include <string.h>
#include <stdio.h>

static constexpr f32 default_frequency = 0.086173f;

struct WaveformGeneratorInstance final : SfxCoreExtensionV2Instance
{
  f32 frequency = default_frequency;
  f32 phase = 0.0f;

  ProcessBlockResult processBlock(f32** inBlock, f32** /*outBlock*/, const i32 blockSize) override
  {
    const f32 phaseIncrement = 2.0f * PI_ * (10.0f + frequency * 4990.0f) / f32(sampleRate());
    for (i32 i = 0; i < blockSize; ++i)
    {
      inBlock[0][i] += sinf(phase);
      phase += phaseIncrement;
    }
    phase = fmodf(phase, 2.0f * PI_);

    memcpy(inBlock[1], inBlock[0], blockSize * sizeof(f32));

    return ProcessBlockResult::ProcessedInInBlock;
  }

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

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

  void getParameterDisplay(const i32 index, char* text) override
  {
    switch (index)
    {
    case 0:
      sprintf(text, "%8.2f", 10.0f + frequency * 4990.0f);
      break;
    default:
      unreachable();
    }
  }

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

static struct WaveformGenerator final : SfxCoreExtensionV2Base
{
  WaveformGenerator()
  {
    RegisterSfxCoreExtensionV2("Waveform Generator", this);
  }

  i32 getParameterCount() const override
  {
    return 1;
  }

  const char* getParameterLabel(const i32 index) override
  {
    switch (index)
    {
    case 0:
      return "Hz";
    default:
      unreachable();
    }
  }

  const char* getParameterName(const i32 index) override
  {
    switch (index)
    {
    case 0:
      return "Frequency";
    default:
      unreachable();
    }
  }

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

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

    return instances[instance];
  }
} waveformGenerator;

#endif // SHR3D_SFX_CORE_EXTENSION_V2
