/* +------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)            |
   |                          https://www.mrpt.org/                         |
   |                                                                        |
   | Copyright (c) 2005-2023, Individual contributors, see AUTHORS file     |
   | See: https://www.mrpt.org/Authors - All rights reserved.               |
   | Released under BSD License. See: https://www.mrpt.org/License          |
   +------------------------------------------------------------------------+ */
#pragma once

#include <mrpt/core/optional_ref.h>
#include <mrpt/core/pimpl.h>
#include <mrpt/io/CStream.h>
#include <mrpt/io/open_flags.h>

namespace mrpt::io
{
/** Saves data to a file and transparently compress the data using the given
 * compression level.
 * The generated files are in gzip format ("file.gz").
 *
 * \sa CFileOutputStream
 * \ingroup mrpt_io_grp
 */
class CFileGZOutputStream : public CStream
{
   private:
	struct Impl;
	mrpt::pimpl<Impl> m_f;

   public:
	/** Constructor: opens an output file with the given compression level
	 * (Default= 1, the minimum, fastest).
	 *
	 * \param fileName The file to be open in this stream
	 * \param append If set to true, the file will be opened for writing and the
	 * current cursor position set at the end of the file. Otherwise, previous
	 * contents will be lost.
	 * \exception std::exception if the file cannot be opened.
	 */
	CFileGZOutputStream(
		const std::string& fileName, const OpenMode mode = OpenMode::TRUNCATE,
		int compressionLevel = 1);

	/** Constructor, without opening the file.
	 * \sa open
	 */
	CFileGZOutputStream();

	CFileGZOutputStream(const CFileGZOutputStream&) = delete;
	CFileGZOutputStream& operator=(const CFileGZOutputStream&) = delete;

	/** Destructor */
	~CFileGZOutputStream() override;

	std::string getStreamDescription() const override;

	/** Open a file for write, choosing the compression level
	 * \param fileName The file to be open in this stream
	 * \param compress_level 0:no compression, 1:fastest, 9:best
	 * \return true on success, false on any error.
	 */
	bool open(
		const std::string& fileName, int compress_level = 1,
		mrpt::optional_ref<std::string> error_msg = std::nullopt,
		const OpenMode mode = OpenMode::TRUNCATE);

	/** Close the file */
	void close();
	/** Returns true if the file was open without errors. */
	bool fileOpenCorrectly() const;
	/** Returns true if the file was open without errors. */
	bool is_open() { return fileOpenCorrectly(); }
	/** Method for getting the current cursor position, where 0 is the first
	 * byte and TotalBytesCount-1 the last one. */
	uint64_t getPosition() const override;

	/** Returns the path of the filename passed to open(), or empty if none. */
	std::string filePathAtUse() const;

	/** This method is not implemented in this class */
	uint64_t Seek(int64_t, CStream::TSeekOrigin = sFromBeginning) override;
	/** This method is not implemented in this class */
	uint64_t getTotalBytesCount() const override;
	size_t Read(void* Buffer, size_t Count) override;
	size_t Write(const void* Buffer, size_t Count) override;
};	// End of class def.
static_assert(
	!std::is_copy_constructible_v<CFileGZOutputStream> &&
		!std::is_copy_assignable_v<CFileGZOutputStream>,
	"Copy Check");
}  // namespace mrpt::io
