#include "multipart_builder.h"

#include <util/random/random.h>
#include <util/system/datetime.h>

#include <vector>
#include <sstream>

namespace maps::mrc::takeout {
namespace {

const std::string CRLF = "\r\n";

const std::string BOUNDARY_PREFIX = "boundary";

std::string randomString(const std::string& prefix)
{
    return prefix + std::to_string(MicroSeconds()) + std::to_string(RandomNumber<ui64>());
}

} // anonymous namespace

std::ostream& operator<<(std::ostream& stream, const BaseFormData& data)
{
    data.encode(stream);
    return stream;
}

void NameValueFormData::encode(std::ostream& stream) const
{
    stream << "Content-Disposition: form-data; name=\"" << name_ << "\"" << CRLF;
    stream << CRLF;
    stream << value_ << CRLF;
}

void JsonAttachmentFormData::encode(std::ostream& stream) const
{
    stream << "Content-Disposition: form-data; name=\"file\"; "
           << "filename=\"" << filename_ << "\"" << CRLF;
    stream << "Content-Type: application/json" << CRLF;
    stream << CRLF;
    stream << attachment_ << CRLF;
}

MultipartBuilder::MultipartBuilder()
    : multipartBoundary_(randomString(BOUNDARY_PREFIX))
{
    content_ << CRLF;
}

void MultipartBuilder::add(const BaseFormData& formData)
{
    content_ << "--" << multipartBoundary_ << CRLF;
    content_ << formData;
}

void MultipartBuilder::fill(http::Request& request) const
{
    std::string contentType = "multipart/form-data; boundary=" + multipartBoundary_;
    request.addHeader("Content-Type", contentType);

    content_ << "--" << multipartBoundary_ << "--" << CRLF;

    request.setContent(content_.str());
}

} // namespace maps::mrc::takeout
