#pragma once

#include <iostream>
#include <memory>

template <size_t len>
std::string readStr(std::istream &str)
{
  char buff[len];
  str.read(buff, len);
  return std::string(buff, len);
}

template <typename T>
T read(std::istream &str)
{
  T res;
  str.read((char *)&res, sizeof(res));
  return res;
}

class WavFile
{
public:
  WavFile(std::istream &str)
  {
    auto chunkId = readStr<4>(str);
    auto chunkSize = read<uint32_t>(str);
    auto format = readStr<4>(str);

    auto subchunk1Id = readStr<4>(str);
    auto subchunk1Size = read<uint32_t>(str);

    auto audioFormat = read<uint16_t>(str);
    numChannels_ = read<uint16_t>(str);
    sampleRate_ = read<uint32_t>(str);
    auto byteRate = read<uint32_t>(str);

    auto blockAlign = read<uint16_t>(str);
    bitsPerSample_ = read<uint16_t>(str);

    auto subchunk2Id = readStr<4>(str);
    dataSize_ = read<uint32_t>(str);

    data_ = std::unique_ptr<char>(new char[dataSize_]);
    str.read(data_.get(), dataSize_);
  }

  uint32_t sampleRate() const { return sampleRate_; }
  uint16_t channels() const { return numChannels_; }
  uint32_t size() const { return dataSize_; }

  const char *operator[](int offset) const { return &data_.get()[offset]; }

private:
  std::unique_ptr<char> data_;
  uint32_t sampleRate_;
  uint16_t bitsPerSample_;
  uint32_t dataSize_;
  uint16_t numChannels_;
};