#pragma once

#include <psemek/io/stream.hpp>

#include <filesystem>
#include <cstdio>

namespace psemek::io
{

	struct file_istream
		: istream
	{
		file_istream() = default;

		file_istream(FILE * file)
			: file_{file}
		{}

		file_istream(std::filesystem::path const & path);

		file_istream(file_istream && s)
			: file_{s.file_}
		{
			s.file_ = nullptr;
		}

		file_istream & operator = (file_istream && s)
		{
			if (this != &s)
			{
				reset();
				file_ = s.file_;
				s.file_ = nullptr;
			}
			return *this;
		}

		void reset();

		std::size_t read(char * p, std::size_t size) override;

		bool finished() const override;

		~file_istream() override
		{
			reset();
		}

	private:
		FILE * file_ = nullptr;
	};

	struct file_ostream
		: ostream
	{
		static constexpr unsigned append = 1;

		file_ostream() = default;

		file_ostream(FILE * file)
			: file_{file}
		{}

		file_ostream(std::filesystem::path const & path, unsigned flags = 0);

		file_ostream(file_ostream && s)
			: file_{s.file_}
		{
			s.file_ = nullptr;
		}

		file_ostream & operator = (file_ostream && s)
		{
			if (this != &s)
			{
				reset();
				file_ = s.file_;
				s.file_ = nullptr;
			}
			return *this;
		}

		void reset();

		std::size_t write(char const * p, std::size_t size) override;

		void flush() override;

		~file_ostream() override
		{
			reset();
		}

	private:
		FILE * file_ = nullptr;
	};

}
