#ifndef OpenTestSystem_OtxDiagManager_Common_Result_H
#define OpenTestSystem_OtxDiagManager_Common_Result_H

#include "CommonDefs.h"
#include "CommonClasses.h"
#include "ProtoClasses.h"
#include "ParameterContainer.h"

namespace OpenTestSystem
{
	namespace OtxDiagManager
	{
		namespace Common
		{
			enum ResultCodesPb : int;
			enum ExceptionTypesPb : int;

			/// <summary>
			/// This class is used for communication between layers. 
			/// <remarks>
			/// The Result contains a Google Protobuf data object, which is the result of execution of command
			/// </remarks>
			/// </summary>
			class COMMON_EXPORTS Result : public ParameterContainer
			{
			public:
				Result();
				Result(const Command& command, int resultCode);
				Result(const Result& otherResult);
				virtual ~Result();

				Result& operator=(const Result& otherResult);

				/// <summary>
				/// Get Client Id in Command.
				/// </summary>
				/// <returns>Client Id.</returns>
				int GetClientId() const;
				/// <summary>
				/// Get unique Command Id.
				/// </summary>
				/// <returns>Unique Command Id.</returns>
				int GetCommandId() const;  // this is the unique id of command

				/// <summary>
				/// Get Command Type. 
				/// <remarks>
				/// E.g: UserCommand = 0 (default), GetComChannel = 1, CreateDiagService = 2, ...
				/// </remarks>
				/// </summary>
				/// <returns>Command Type.</returns>
				int GetCommandType() const; // this is command type, e.g: UserCommand = 0 (default), GetComChannel = 1, CreateDiagService = 2, ...

				/// <summary>
				/// Get Command Name in Result.
				/// </summary>
				/// <returns>Command Name.</returns>
				std::string GetCommandName() const;

				/// <summary>
				/// Set result code in Result.
				/// </summary>
				/// <remarks>
				/// Success = 0; Pending = 1; Failed = 2; NoResponse = 3; NegResponse = 4;
				///</remarks>
				/// <param name="clientId">Client Id.</param>
				void SetResultCode(ResultCodesPb resultcode);
				/// <summary>
				/// Get result code in Result.
				/// </summary>
				/// <remarks>
				/// Success = 0; Pending = 1; Failed = 2; NoResponse = 3; NegResponse = 4;
				///</remarks>
				/// <returns>Result code.</returns>
				int GetResultCode() const;

				/// <summary>
				/// Is this result of asynchronous execution of command.
				/// </summary>
				/// <returns>Asynchronous = True, synchronous = False.</returns>
				bool IsAsyncResult() const;

				/// <summary>
				/// Set exception data into result.
				/// </summary>
				/// <param name="errorcode">Exception error code.</param>
				/// <param name="type">Exception type. E.g: UnknownException = 0; InvalidReferenceException = 1; OutOfBoundsException = 2; TypeMismatchException = 3; ...</param>
				/// <param name="message">Exception message.</param>
				void SetExceptionData(int errorcode, ExceptionTypesPb type, const std::string& message);

				/// <summary>
				/// Get exception data from result.
				/// </summary>
				/// <param name="errorcode">Exception error code.</param>
				/// <param name="type">Exception type. E.g: UnknownException = 0; InvalidReferenceException = 1; OutOfBoundsException = 2; TypeMismatchException = 3; ...</param>
				/// <param name="message">Exception message.</param>													
				void GetExceptionData(int& errorcode, ExceptionTypesPb& type, std::string& message) const;

				/// <summary>
				/// Serialize the internal Google Protobuf data object in the output string.
				/// </summary>
				/// <param name="output">Output string.</param>	
				void Serialize(std::string* output) const override;

				/// <summary>
				/// Deserialize the data string into the internal Google Protobuf data object.
				/// </summary>
				/// <param name="data">Output string.</param>
				void Deserialize(const std::string& data) override;

			private:
				int _clientId;
				bool _isAsyncResult;
				CommandDataPb* _resultData;
			};
		}
	}
}
#endif // OpenTestSystem_OtxDiagManager_Common_Result_H
