/*************************************************************************
 * libjson-rpc-cpp
 *************************************************************************
 * @file    windowstcpsocketclient.h
 * @date    17.07.2015
 * @author  Alexandre Poirot <alexandre.poirot@legrand.fr>
 * @license See attached LICENSE.txt
 ************************************************************************/

#ifndef JSONRPC_CPP_WINDOWSTCPSOCKETCLIENT_H_
#define JSONRPC_CPP_WINDOWSTCPSOCKETCLIENT_H_

#include <jsonrpccpp/common/exception.h>
#include <string>
#include "tcpsocketclientprivate.h"
#include <winsock2.h>

namespace jsonrpc
{
	/**
	 * This class is the windows implementation of TCPSocketClient.
	 * It uses the Winsock2 API to performs its job.
	 */
	class WindowsTcpSocketClient : public TcpSocketClientPrivate
	{
		public:
			/**
			 * @brief WindowsTcpSocketClient, constructor of the Windows implementation of class TcpSocketClient
			 * @param hostToConnect The hostname or the ipv4 address on which the client should try to connect
			 * @param port The port on which the client should try to connect
			 */
			WindowsTcpSocketClient(const std::string& hostToConnect, const unsigned int &port);
			/**
			 * @brief ~WindowsTcpSocketClient, the destructor of WindowsTcpSocketClient
			 */
			virtual ~WindowsTcpSocketClient();
			/**
			 * @brief The real implementation of TcpSocketClient::SendRPCMessage method.
			 * @param message The message to send
			 * @param result The result of the call returned by the server
			 * @throw JsonRpcException Thrown when an issue is encounter with socket manipulation (see message of exception for more information about what happened).
			 */
			virtual void SendRPCMessage(const std::string& message, std::string& result) throw (JsonRpcException);

		private:
			std::string hostToConnect;    /*!< The hostname or the ipv4 address on which the client should try to connect*/
			unsigned int port;          /*!< The port on which the client should try to connect*/
			/**
			 * @brief A method to produce human readable messages from Winsock2 error values.
			 * @param e A Winsock2 error value
			 * @return The message matching the error value
			 */
			static std::string GetErrorMessage(const int &e);
			/**
			 * @brief Connects to the host and port provided by constructor parameters.
			 * 
			 * This method detects if the hostToConnect attribute is either an IPv4 or a hostname.
			 * On first case it tries to connect to the ip.
			 * On second case it tries to resolve hostname to an ip and tries to connect to it if resolve was successful.
			 * 
			 * @returns A file descriptor to the successfully connected socket
			 * @throw JsonRpcException Thrown when an issue is encountered while trying to connect (see message of exception for more information about what happened).
			 */
			SOCKET Connect() throw (JsonRpcException);
			/**
			 * @brief Connects to provided ip and port.
			 * 
			 * This method tries to connect to the provided ip and port.
			 * 
			 * @param ip The ipv4 address to connect to
			 * @param port The port to connect to
			 * @returns A file descriptor to the successfully connected socket
			 * @throw JsonRpcException Thrown when an issue is encountered while trying to connect (see message of exception for more information about what happened).
			 */
			SOCKET Connect(const std::string& ip, const int& port) throw (JsonRpcException);
			/**
			 * @brief Check if provided ip is an ipv4 address.
			 * 
			 * @param ip The ipv4 address to check
			 * @returns A boolean indicating if the provided ip is or is not an ipv4 address
			 */
			bool IsIpv4Address(const std::string& ip);
	};

} /* namespace jsonrpc */
#endif /* JSONRPC_CPP_WINDOWSTCPSOCKETCLIENT_H_ */
