#include "json_formatter.h"
#include "common.h"
#include "json_common.h"
#include <yandex/maps/wiki/common/json_helpers.h>
#include <yandex/maps/wiki/common/date_time.h>

namespace maps {
namespace wiki {
namespace {
void
serializeBranch(json::ObjectBuilder& branchBuilder, const revision::Branch& branch, bool first/* = false*/)
{
    const auto type = branch.type();
    const bool isProduction = type == revision::BranchType::Archive && first;
    branchBuilder[STR_ID] = common::idToJson(branch.id());
    branchBuilder[STR_TYPE] = isProduction
        ? BRANCH_TYPE_PRODUCTION
        : boost::lexical_cast<std::string>(type);
    branchBuilder[STR_STATE] = boost::lexical_cast<std::string>(branch.state());
    if (type == revision::BranchType::Trunk
        || type == revision::BranchType::Approved) {
        return;
    }
    branchBuilder[STR_CREATED] = common::canonicalDateTimeString(
            branch.createdAt(), common::WithTimeZone::Yes);
    branchBuilder[STR_CREATEDBY] =  common::idToJson(branch.createdBy());
    if (branch.finishedBy()) {
        branchBuilder[STR_PUBLISHED] = common::canonicalDateTimeString(
            branch.finishedAt(), common::WithTimeZone::Yes);
        branchBuilder[STR_PUBLISHEDBY] =  common::idToJson(branch.finishedBy());
    }
}
}//namespace

std::string
JSONFormatter::operator ()(const ResultType<GetBranches>& result)
{
    JsonBuilder builder;
    std::set<revision::BranchType> branchTypeVisited;
    builder << [&](json::ObjectBuilder branchesBuilder) {
        branchesBuilder[STR_BRANCHES]  << [&](json::ArrayBuilder branchesArray) {
            for (const auto& branch : result.branches) {
                bool first = branchTypeVisited.insert(branch.type()).second;
                branchesArray << [&](json::ObjectBuilder branchBuilder) {
                    serializeBranch(branchBuilder, branch, first);
                };
            }
        };
    };
    return builder.str();
}

} //wiki
} //maps
