#pragma once

#include <iostream>
#include <utility>
#include <algorithm>
#include <string>
#include <cmath>
#include <memory>

class BufferedReader {
 public:
    explicit BufferedReader(PackageStream *stream) : stream(stream) {
        char* tmp_buf = new char[stream->PackageLen() + 1];
        while (true) {
            memset(tmp_buf, 0, stream->PackageLen() + 1);
            auto result = stream->ReadPackage(tmp_buf);
            if (result > 0) {
                buffer += string(tmp_buf);
            } else {
                break;
            }
        }
        delete[] tmp_buf;
    }
    int32_t Read(char *output_buffer, int32_t buffer_len) {
        int32_t next_pos = min<int32_t>(buffer.size(),  pos_ + buffer_len);
        int32_t len = next_pos - pos_;

        memcpy(output_buffer, buffer.c_str() + pos_, len);
        this->pos_ = next_pos;
        return len;
    }

 private:
    PackageStream *stream;
    string buffer;

    int32_t pos_ = 0;
};