/*
 * Copyright © 2020-2026 Pierrick Caillon <pierrick.caillon+zipdirfs@megami.fr>
 */
#ifndef ZIPDIRFS_ZIP_EXCEPTION_H
#define ZIPDIRFS_ZIP_EXCEPTION_H

#include <exception>
#include <ostream>
#include <string>

namespace ZipDirFs::Zip
{
	/**
	 * @brief An exception thrown when accessing zip archive
	 * @authors Pierrick Caillon <pierrick.caillon+zipdirfs@megami.fr>
	 */
	class Exception : public std::exception
	{
	public:
		Exception(const std::string&, const std::string&) _GLIBCXX_USE_NOEXCEPT;
		Exception(const std::string&, const std::string&, int zipErrCode,
			int zipSystemCode) _GLIBCXX_USE_NOEXCEPT;
		~Exception() _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT override;
		[[nodiscard]] const char* what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT override;
		[[nodiscard]] int code() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT;
		static Exception fromErrorno(const std::string& s, int) _GLIBCXX_USE_NOEXCEPT;

	private:
		Exception(const std::string&, const std::string&, int errorno) _GLIBCXX_USE_NOEXCEPT;
		const std::string source;
		const std::string message;
		const int errorno;
		friend std::ostream& operator<<(std::ostream&, const Exception&);
	};

	std::ostream& operator<<(std::ostream&, const Exception&);
	int zipErrorCode(int code) _GLIBCXX_USE_NOEXCEPT;
	int zipSystemCode(int code) _GLIBCXX_USE_NOEXCEPT;

} // namespace ZipDirFs::Zip

#endif // ZIPDIRFS_ZIP_EXCEPTION_H
