#include "socket_adapter_proto2json_ref.h"

#include <saas/api/clientapi.h>
#include <saas/library/behaviour/behaviour.h>
#include <saas/util/json/json.h>

#include <library/cpp/http/multipart/send.h>
#include <library/cpp/logger/global/global.h>

#include <util/generic/yexception.h>

namespace {
    void BuildJsonRef(const NRTYServer::TMessage& message, TStringStream& data, const TString& boundary = DefaultBoundary) {
        NSaas::TAction action;
        action.ParseFromProtobuf(message);
        TToJsonContext context(TToJsonContext::JSON_REF);
        TString jsonMessage = NUtil::JsonToString(action.ToJson(context), true);
        context.Parts.emplace_back(TString("json_message"), jsonMessage);
        TStringStream body;
        for (const auto& part : context.Parts) {
            body << "\r\n--" << boundary << "\r\n";
            body << "Content-Disposition: form-data; name=\"" << part.first << "\"\r\n";
            body << "Content-Length: " << part.second.size() << "\r\n";
            body << "\r\n" << part.second;
        }
        body << "\r\n--" << boundary << "--\r\n";

        data << "Content-Type: multipart/form-data; boundary=" << boundary << "\r\n";
        data << "Content-Length: " << body.Size() << "\r\n";
        data << "\r\n" << body.Str();
    }
}

TSocketAdapterProto2JsonRef::TSocketAdapterProto2JsonRef(const TString& service, IInputStream& input, IOutputStream& output, bool realtime)
:TSocketAdapterProto2Json(service, input, output, realtime)
{
}

void TSocketAdapterProto2JsonRef::WriteMessage(const ::google::protobuf::Message& message, const TString& request) const {
    Y_VERIFY(!UsedToWrite, "TSocketAdapterProto2JsonRef: only one message to socket");
    UsedToWrite = true;
    const NRTYServer::TMessage& messageRTY = dynamic_cast<const NRTYServer::TMessage&>(message);
    MessageId = messageRTY.GetMessageId();
    TStringStream ss;
    ss << "POST /service/" << Service << "?ftests=yes" << (Realtime ? "" : "&realtime=no") << request << " HTTP/1.1\r\n";
    BuildJsonRef(messageRTY, ss);
    Output << ss.Str();
    Output.Flush();
}

void TSocketAdapterProto2JsonRef::WriteMessage(const TString& /*message*/, const TString& /*request*/) const {
    ythrow yexception() << "Not implemented: 'Send(TString)'";
}
