#pragma once

class BufferedReader {
 public:
    explicit BufferedReader(PackageStream* stream) : stream(stream) {
        data = new char[stream->PackageLen()];
        len = stream->ReadPackage(data);
    }

    int32_t Read(char* output_buffer, int32_t buffer_len) {
        int32_t readed = 0;
        while (len <= buffer_len - readed && len != 0) {
            memcpy(output_buffer + readed, data, len);
            readed += len;
            len = stream->ReadPackage(data);
        }

        if (len != 0) {
            char* buf = new char[len - (buffer_len - readed)];
            memcpy(output_buffer + readed, data, buffer_len - readed);
            memcpy(buf, data + buffer_len - readed,
                    len - (buffer_len - readed));
            memcpy(data, buf, len - (buffer_len - readed));
            delete[] buf;
            len -= buffer_len - readed;
            readed = buffer_len;
        }
        return readed;
    }

    ~BufferedReader() {
        delete[] data;
    }

 private:
    PackageStream* stream;
    char* data;
    int32_t len;
};