/************************************************
*
*  Chunked Data Source
*  Copyright (C) 2020
*  John Ryland
*  All rights reserved
*
************************************************/
#pragma once
#ifndef CHUNKED_DATA_SOURCE_HPP
#define CHUNKED_DATA_SOURCE_HPP

#include "DataSource.hpp"

class ChunkedDataSource
{
public:
    enum class ReadResult
    {
        eSuccess,
        eError
    };

    // For disks, a recommended size of not less than 4kb (page size) and not
    // more than 512kb (potential size of the L2/L3 cache).
    // For SSD drives, a good size might be 64kb or 128kb.
    // BUFSIZ presently is set to 8kb, and might be out of date with respect to modern systems.
    ChunkedDataSource(size_t aChunkSize = BUFSIZ, unsigned aRetryAttempts = 3);
    virtual ~ChunkedDataSource() = default;

    virtual size_t GetDataSize() = 0;
    virtual ReadResult ReadChunk(std::vector<uint8_t>& aBuffer) = 0;

    size_t ChunkSize() const { return mChunkSize; }

    // O_DIRECT flag
    // OS read/write vs stdio fread/fwrite
    // network read/write vs filesystem

private:
    size_t    mChunkSize;
    unsigned  mRetryAttempts;
};

class ChunkedReaderProxy : public OpenedDataSource
{
public:
    // Doesn't take ownership of aProxiedSource
    explicit ChunkedReaderProxy(ChunkedDataSource& aProxiedSource);
    ~ChunkedReaderProxy() override;

    //! Reads in bytes from the data source
    //! @param aNumberOfBytes is the number of bytes to read
    //! @param aCallback is the continuation when the read finishes
    //! @returns true if success otherwise false
    bool ReadBytes(size_t aNumberOfBytes, ReadCompletionCallback aCallback) override;
    bool ReadLine(ReadCompletionCallback aCallback) override;
    bool ReadAll(ReadCompletionCallback aCallback) override;
private:
    ChunkedDataSource&    mProxiedSource;
    std::vector<uint8_t>  mBufferedData;
    size_t                mBufferIndex;
};

#endif // CHUNKED_DATA_SOURCE_HPP
