#include "get_rich_content.h"

#include "maps/wikimap/mapspro/services/editor/src/branch_helpers.h"
#include "maps/wikimap/mapspro/services/editor/src/configs/config.h"
#include "maps/wikimap/mapspro/services/editor/src/utils.h"

#include <maps/libs/log8/include/log8.h>
#include <yandex/maps/wiki/configs/editor/categories.h>
#include <yandex/maps/wiki/revision/revisionsgateway.h>

#include <algorithm>
#include <string>
#include <sstream>

namespace maps {
namespace wiki {

std::string
GetRichContent::Request::dump() const
{
    std::stringstream ss;
    ss << " uid: " << uid;
    ss << " objectId: " << objectId;
    ss << " revisionId: " << revisionId;
    ss << " branchId: " << branchId;
    ss << " token: " << token;
    return ss.str();
}

GetRichContent::GetRichContent(const Request& request)
    : controller::BaseController<GetRichContent>(BOOST_CURRENT_FUNCTION)
    , request_(request)
{
}

GetRichContent::~GetRichContent()
{
}

std::string
GetRichContent::printRequest() const
{
    return request_.dump();
}

void
GetRichContent::control()
{
    auto branchCtx = BranchContextFacade::acquireRead(
        request_.branchId, request_.token);

    revision::RevisionsGateway gateway(branchCtx.txnCore(), branchCtx.branch);
    gateway.reader().setDescriptionLoadingMode(revision::DescriptionLoadingMode::Load);

    WIKI_REQUIRE(
        request_.objectId == request_.revisionId.objectId(),
        ERR_BAD_REQUEST,
        "Given object id doesn't match given revision");

    auto revision = gateway.reader().tryLoadRevision(request_.revisionId);

    WIKI_REQUIRE(
        revision && !revision->data().deleted,
        ERR_MISSING_OBJECT,
        "Object revision " << request_.revisionId << " never existed or was deleted");

    auto& revisionData = revision->data();

    //putting corresponding headers
    const auto& attributes = *(revisionData.attributes);
    std::string categoryId;
    for (const auto& attribute: attributes) {
        categoryId = canonicalCategoryIdToPlain(attribute.first);
        if (!categoryId.empty()) {
            break;
        }
    }
    const auto& category = cfg()->editor()->categories()[categoryId];
    WIKI_REQUIRE(
        !category.richContentType().empty(),
        ERR_BAD_REQUEST,
        "RichContentType isn't set for category " << categoryId);

    //thegeorg@FIXME:
    //here is a hidden knowledge about
    //description <-> richContent correspondence
    WIKI_REQUIRE(
        revision->hasDescription(),
        ERR_MISSING_OBJECT,
        "Object " << request_.objectId << " has no description");

    result_->decodedData = decodeBase64(*revisionData.description);

    std::stringstream contentDispositionStream;
    contentDispositionStream
            << "attachment; filename=rich-content."
            << request_.objectId << "."
            << category.richContentFileExt();
    result_->contentDisposition = contentDispositionStream.str();
    result_->contentType = category.richContentType();
}

} //namespace wiki
} //namespace maps
