#pragma once
#include "serializer.h"
#include "lsRequestId.h"
#include "LibLsp/JsonRpc/message.h"
#include "LibLsp/lsp/method_type.h"

struct ResponseInMessage : public LspMessage
{

   lsRequestId id;
   std::string m_methodType;

   virtual MethodType GetMethodType() const override
   {
       return m_methodType.data();
   };
   virtual void SetMethodType(MethodType _type) override
   {
       m_methodType = _type;
   };

   Kind GetKid() override
   {
       return RESPONCE_MESSAGE;
   }
   virtual bool IsErrorType()
   {
       return false;
   }
};
template<class TDerived>
struct BaseResponseMessage : ResponseInMessage
{

   void ReflectWriter(Writer& writer) override
   {
       Reflect(writer, static_cast<TDerived&>(*this));
   }
   static std::unique_ptr<LspMessage> ReflectReader(Reader& visitor)
   {

       TDerived* temp = new TDerived();
       std::unique_ptr<TDerived> message = std::unique_ptr<TDerived>(temp);
       // Reflect may throw and *message will be partially deserialized.
       Reflect(visitor, static_cast<TDerived&>(*temp));
       return message;
   }
};

template<class T, class TDerived>
struct ResponseMessage : BaseResponseMessage<TDerived>
{
   T result;
   void swap(ResponseMessage<T, TDerived>& arg) noexcept
   {
       std::swap(result, arg.result);
       this->id.swap(arg.id);
       this->m_methodType.swap(arg.m_methodType);
   }
};

template<class T, class TDerived>
struct ResponseError : BaseResponseMessage<TDerived>
{
   T error;
   bool IsErrorType() override
   {
       return true;
   }
   void swap(ResponseError<T, TDerived>& arg) noexcept
   {

       this->id.swap(arg.id);
       this->m_methodType.swap(arg.m_methodType);
       std::swap(error, arg.error);
   }
};