#pragma once

#include <cstdint>
#include <string>
#include <vector>

#include "core/audio_types.h"

namespace aptt {

struct NativeDsdConfig {
  std::uint32_t dsd_rate_multiplier = 64;
  std::uint32_t channel_count = 2;
  SampleType sample_type = SampleType::kDsd1BitLsbFirst;
};

struct NativeDsdGenerationResult {
  bool ok = false;
  std::string error;
  FormatDescriptor format;
  std::vector<std::vector<std::uint8_t>> channel_payloads;
};

struct NativeDsdSineConfig {
  NativeDsdConfig dsd;
  double frequency_hz = 1000.0;
  double amplitude_dbfs = -20.0;
};

std::uint32_t NativeDsdRateHz(std::uint32_t dsd_rate_multiplier);
bool IsSupportedNativeDsdRate(std::uint32_t dsd_rate_multiplier);
bool IsSupportedNativeDsdSampleType(SampleType sample_type);
const char* NativeDsdSampleTypeName(SampleType sample_type);
const char* NativeDsdByteOrderName(SampleType sample_type);
FormatDescriptor MakeNativeDsdFormat(const NativeDsdConfig& config);

NativeDsdGenerationResult GenerateNativeDsdIdle(
    const NativeDsdConfig& config,
    std::uint32_t byte_count_per_channel);
NativeDsdGenerationResult GenerateNativeDsdTestPattern(
    const NativeDsdConfig& config,
    std::uint32_t byte_count_per_channel);

class NativeDsdSineGenerator {
 public:
  void Reset();
  NativeDsdGenerationResult GenerateSine(
      const NativeDsdSineConfig& config,
      std::uint32_t byte_count_per_channel);
  NativeDsdGenerationResult GenerateIdle(
      const NativeDsdConfig& config,
      std::uint32_t byte_count_per_channel);

 private:
  void EnsureChannelState(std::uint32_t channel_count);

  std::uint64_t dsd_sample_index_ = 0;
  std::vector<double> modulators_;
};

}  // namespace aptt
