#pragma once
#include "buffer.h"
#include "randomaccessaudioreadable.h"

class RemoteAudioBuffer : public RandomAccessAudioReadable {
  const int sampleRate;
  const int channelCount;
  const int frameCount;

public:
  RemoteAudioBuffer(int sampleRate, int channelCount, int frameCount)
      : sampleRate(sampleRate), channelCount(channelCount),
        frameCount(frameCount) {}

  virtual void read(int frameOffset, std::shared_ptr<BufferF32> output) {
    auto outputAsSlice = output->slice(0, output->getFrameCount());
    read(frameOffset, outputAsSlice);
  }

  virtual void read(int frameOffset, BufferF32 output) = 0;

  virtual int getSampleRate() const { return sampleRate; }
  virtual int getChannelCount() const { return channelCount; }
  virtual int getFrameCount() const { return frameCount; }
};

class BufferAsRemoteAudioBuffer final : public RemoteAudioBuffer {
  std::shared_ptr<BufferF32> underlyingBuffer;

public:
  BufferAsRemoteAudioBuffer(int sampleRate,
                            std::shared_ptr<BufferF32> underlyingBuffer)
      : RemoteAudioBuffer(sampleRate, underlyingBuffer->getChannelCount(),
                          underlyingBuffer->getFrameCount()),
        underlyingBuffer(underlyingBuffer) {}

  void read(int frameOffset, BufferF32 output) override {
    for (int i = 0; i < getChannelCount(); i++) {
      const auto inData = underlyingBuffer->getChannelData(i);
      auto outData = output.getChannelData(i);
      memcpy(outData, inData + frameOffset,
             output.getFrameCount() * sizeof(float));
    }
  }

  std::shared_ptr<RandomAccessAudioReadable> clone() const override {
    return std::make_shared<BufferAsRemoteAudioBuffer>(getSampleRate(),
                                                       underlyingBuffer);
  }
};