#pragma once

#include <frostbite2D/types/type_alias.h>

#include <fstream>
#include <string>
#include <vector>

namespace frostbite2D {

class BinaryFileStreamReader {
public:
  BinaryFileStreamReader() = default;
  explicit BinaryFileStreamReader(const std::string& filePath);
  ~BinaryFileStreamReader();

  bool open(const std::string& filePath);
  void close();
  bool isOpen() const;

  size_t tell() const;
  void seek(size_t pos);
  void skip(size_t count);
  bool eof() const;

  size_t size() const;
  size_t remaining() const;
  size_t lastReadCount() const;

  size_t read(char* buffer, size_t size);
  std::vector<uint8> readBytes(size_t size);

  template <typename T>
  T read() {
    T value{};
    read(reinterpret_cast<char*>(&value), sizeof(T));
    return value;
  }

  int8 readInt8();
  int16 readInt16();
  int32 readInt32();
  int64 readInt64();
  uint8 readUInt8();
  uint16 readUInt16();
  uint32 readUInt32();
  uint64 readUInt64();
  float readFloat();
  double readDouble();

  std::string readString(size_t length);
  std::string readNullTerminatedString(size_t maxLength = 4096);

private:
  std::ifstream stream_;
  std::string filePath_;
  size_t size_ = 0;
  size_t position_ = 0;
  size_t lastReadCount_ = 0;
};

} // namespace frostbite2D
