/*
    libmaus2
    Copyright (C) 2020 German Tischler

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#if ! defined(LIBMAUS2_NETWORK_CURLOBJECT_HPP)
#define LIBMAUS2_NETWORK_CURLOBJECT_HPP

#include <libmaus2/network/CurlOutputBlock.hpp>
#include <libmaus2/network/CurlResponseAcceptor.hpp>

#include <libmaus2/parallel/LockedFreeList.hpp>
#include <libmaus2/parallel/StdSemaphore.hpp>
#include <libmaus2/parallel/StdTerminatableSynchronousQueue.hpp>
#include <libmaus2/parallel/StdMutex.hpp>

namespace libmaus2
{
	namespace network
	{
		struct CurlObject
		{
			void * vcurl;
			libmaus2::util::AutoArrayCharBaseAllocator AFLalloc;
			libmaus2::parallel::StdSemaphore sem;
			libmaus2::parallel::LockedFreeList<libmaus2::autoarray::AutoArray<char>,libmaus2::util::AutoArrayCharBaseAllocator,libmaus2::util::AutoArrayCharBaseTypeInfo> AFL;
			libmaus2::parallel::StdTerminatableSynchronousQueue<CurlOutputBlock> outputQueue;

			std::atomic<long> response;
			std::atomic<bool> responseSet;
			std::atomic<long> lastResponse;

			std::ostringstream headerstr;

			libmaus2::network::CurlResponseAcceptor * acceptor;

			CurlObject(
				std::string const &
					#if defined(LIBMAUS2_HAVE_LIBCURL)
					url
					#endif
					,
				libmaus2::network::CurlResponseAcceptor *
					#if defined(LIBMAUS2_HAVE_LIBCURL)
					racceptor = nullptr
					#endif
					,
				uint64_t const
					#if defined(LIBMAUS2_HAVE_LIBCURL)
					freelistsize
					#endif
					= 4
			);
			~CurlObject();

			std::pair<int,std::string> perform();
			::std::size_t read(
				char *
				#if defined(LIBMAUS2_HAVE_LIBCURL)
					p
				#endif
					,
				::std::size_t
				#if defined(LIBMAUS2_HAVE_LIBCURL)
					n
				#endif
			);

			::std::size_t write_callback(
				char *
				#if defined(LIBMAUS2_HAVE_LIBCURL)
					ptr
				#endif
					,
				::std::size_t
				#if defined(LIBMAUS2_HAVE_LIBCURL)
					size
				#endif
					,
				::std::size_t
				#if defined(LIBMAUS2_HAVE_LIBCURL)
					nmemb
				#endif
			);

			static ::std::size_t write_callback_static(
				char *
					#if defined(LIBMAUS2_HAVE_LIBCURL)
					ptr
					#endif
					,
				::std::size_t
					#if defined(LIBMAUS2_HAVE_LIBCURL)
					size
					#endif
					,
				::std::size_t
					#if defined(LIBMAUS2_HAVE_LIBCURL)
					nmemb
					#endif
					,
				void *
					#if defined(LIBMAUS2_HAVE_LIBCURL)
					userdata
					#endif
			);

			static ::std::size_t header_callback_static(
				char *
					#if defined(LIBMAUS2_HAVE_LIBCURL)
					buffer
					#endif
					,
				std::size_t
					#if defined(LIBMAUS2_HAVE_LIBCURL)
					size
					#endif
					,
				std::size_t
					#if defined(LIBMAUS2_HAVE_LIBCURL)
					nitems
					#endif
					,
				void *
					#if defined(LIBMAUS2_HAVE_LIBCURL)
					userdata
					#endif
			);

			::std::size_t header_callback(
				char *
					#if defined(LIBMAUS2_HAVE_LIBCURL)
					buffer
					#endif
					,
				std::size_t
					#if defined(LIBMAUS2_HAVE_LIBCURL)
					size
					#endif
					,
				std::size_t
					#if defined(LIBMAUS2_HAVE_LIBCURL)
					nitems
					#endif
			);
		};
	}
}
#endif
