#pragma once

#include "ehs/EHS.h"
#include "ehs/Vector.h"
#include "ehs/Str.h"
#include "ehs/json/Json.h"
#include "Socket.h"

namespace ehs
{
	class EHS_LIB_IO Response
	{
	private:
		UInt_32 code;
		Str_8 server;
		ContentType cType;
		Vector<Str_8> header;
		Str_8 body;

	public:
        /// Default member initialization.
        Response();

        /// Initializes this response with a given code and server identifier.
        /// @param [in] code The code to give.
        /// @param [in] server The server identifier.
		Response(const UInt_32 code, const Str_8& server);

        /// Initializes this response with the raw response data.
        /// @param [in] data The C-style string of the response.
        /// @param [in] size The size of the given C-style string.
		Response(const char* data, const UInt_64 size);

        /// Initializes this response with the raw response data.
        /// @param [in] data The string of the response.
		Response(const Str_8& data);

        /// Copies members from another object of the same type.
        /// @param [in] res The object to copy from.
		Response(const Response& res) = default;

        /// Copies members from another object of the same type.
        /// @param [in] res The object to copy from.
        /// @returns The response that has been assigned to.
		Response& operator=(const Response& res);

		/// Sets the response code to send to the endpoint.
		/// @param [in] code The code for success, error or info.
		void SetCode(const UInt_32 code);

		/// Retrieves the response code.
		/// @returns The result.
		UInt_32 GetCode() const;

		/// Sets the server identifier.
		/// @param [in] server The server identifier to use.
		void SetServer(const Str_8& server);

		/// Retrieves the server identifier.
		/// @returns The result.
		Str_8 GetServer() const;

        /// Sets the content type for the body.
        /// @param [in] cType The content type to use.
		void SetContentType(const ContentType cType);

        /// Retrieves the content type for the body.
        /// @returns The result.
		ContentType GetContentType() const;

        /// Adds a header variable.
        /// @param [in] var The variable identifier.
        /// @param [in] value The value of the variable.
		void AddToHeader(const Str_8& var, const Str_8& value);

        /// Retrieves a header variable.
        /// @param [in] var The variable identifier to look for.
        /// @returns The value of the header variable. Empty if it was not found.
		Str_8 GetHeader(const Str_8& var) const;

        /// Retrieves all the header variables in a vector object.
        /// @returns The result.
		Vector<Str_8> GetHeader() const;

        /// Adds a body variable.
        /// @param [in] var The variable identifier.
        /// @param [in] value The value of the variable.
		void AddToBody(const Str_8& var, const Str_8& value);

        /// Adds a value to the body.
        /// @param [in] data The value to add.
		void AddToBody(const Str_8& data);

        /// Sets the entire body.
        /// @param [in] body The body to use.
		void SetBody(const Str_8& body);

        /// Retrieves a body variable.
        /// @param [in] var The variable identifier to look for.
        /// @returns The value of the body variable. Empty if it was not found.
		Str_8 GetVar(const Str_8& var) const;

        /// Retrieves the entire body.
        /// @returns The result.
		Str_8 GetBody() const;

        /// Retrieves the entire body as a Json.
        /// @returns The result.
		Json GetJson() const;

        /// Forms the raw result of the response to be sent.
        /// @returns The result.
		Str_8 FormResult() const;

		bool IsValid() const;

	private:
		static Str_8 CodeToStr(const UInt_32 code);

		static Str_8 ContentTypeToStr(const ContentType cType);

		static ContentType StrToContentType(const Str_8& value);

		void ReadData(const Str_8& data);

	};
}