#pragma once

#ifdef _WIN32
# include <WinSock2.h>
# include <WS2tcpip.h>
#elif defined(__ORBIS__)
# include <net.h>
#endif

namespace TwitchInGames {
#ifdef _WIN32
	using socket_t= SOCKET;
#elif defined(__ORBIS__)
	using socket_t= SceNetId;
#else
# error "unknown platform"
#endif

	struct Socket {
	public:
		Socket();
		~Socket();
		void Connect(string_t hostName, unsigned short port);
		int Receive(void* buffer, size_t size) noexcept;
		template<typename T>
		int ReceiveAll(T& buffer) noexcept {
			for(decltype(buffer.size()) i= 0; i < buffer.size();) {
				auto result= Receive(&buffer[i], buffer.size() - i);
				if(result > 0) {
					i += result;
				} else {
					return result;
				}
			}
			return static_cast<int>(buffer.size());
		}
		int Send(void const* buffer, size_t size) noexcept;
		template<typename T>
		int Send(T const& buffer) noexcept { return buffer.empty() ? 0 : Send(&buffer[0], buffer.size()); }
		int SendAll(void const* buffer, size_t size) noexcept {
			for(decltype(size) i= 0; i < size;) {
				auto const result= Send(reinterpret_cast<char const*>(buffer) + i, size - i);
				if(result > 0) {
					i += result;
				} else {
					return result;
				}
			}
			return static_cast<int>(size);
		}
		template<typename T>
		int SendAll(T const& buffer) noexcept { return buffer.empty() ? 0 : SendAll(&buffer[0], buffer.size()); }
		void Shutdown() noexcept;

	private:
		socket_t value;
	};
}
