#pragma once

#include "IMapSource.h"
#include "tl/memory_buffer.h"
#include "fs/Api.h"

namespace fs
{
class MemorySink;

class FS_API MemorySource final : public IMapSource
{
	friend class MemorySink;
public:
	// The source will make an internal copy of the data passed by the constructor
	// rawMemory can be safely destroyed after calling the constructor
	explicit MemorySource(tl::span<const uint8_t> data);
	explicit MemorySource(MemorySink& sink);
	explicit MemorySource(const tl::memory_buffer& memoryBuffer);

	MemorySource(MemorySource&&) = default;
	MemorySource& operator=(MemorySource&&) = default;
	
	//we have another constructor for empty source
	MemorySource() = default;
	~MemorySource() override = default;

	tl::optional<Error> getLastError() const override;

	size_t read(tl::span<uint8_t> data) override;

	void seekBeg(uint64_t offset) override;
	void seekRel(int64_t offset) override;

	uint64_t tell() const override;
	uint64_t getSize() const override;

	tl::span<const uint8_t> map(size_t size) override;

	void swap(MemorySink& sink);

	bool isEOS() const override;

	size_t getPreferredBufferSize() const override;

protected:
	tl::memory_buffer m_data;

private:
	size_t m_offset = 0;
	mutable tl::optional<Error> m_optLastError;
};

}

