#include "coords_feed_formatter.h"

#include "formatter_helpers.h"
#include "poi_def.h"
#include "component_feed/feed_component.h"

#include <maps/libs/common/include/exception.h>

#include <ostream>
using namespace std::string_literals;

namespace maps::wiki::poi {
namespace {
const auto TEMPLATE_KEY = "company_coords_template"s;

const char COMPANY_COORDS_XML_TEMPLATE[] = R"(
{{%AUTOESCAPE context="XML"}}
<company>
  <company-id>{{POI_ID}}</company-id>
  <coordinates>
    <lon>{{POI_LON}}</lon>
    <lat>{{POI_LAT}}</lat>
  </coordinates>

  {{#POI_PUBLISHING_STATUS_SECTION}}
  <publishing-status>{{POI_PUBLISHING_STATUS}}</publishing-status>
  {{/POI_PUBLISHING_STATUS_SECTION}}

  {{#POI_PERMALINK_SECTION}}
  <permalink>{{POI_PERMALINK}}</permalink>
  {{/POI_PERMALINK_SECTION}}

  {{#POI_RUBRIC_ID_SECTION}}
  <rubric-id>{{POI_RUBRIC_ID}}</rubric-id>
  {{/POI_RUBRIC_ID_SECTION}}

  {{#POI_SECONDARY_RUBRIC_IDS_SECTION}}
  <secondary-rubric-id>{{POI_SECONDARY_RUBRIC_ID}}</secondary-rubric-id>
  {{/POI_SECONDARY_RUBRIC_IDS_SECTION}}

  <actualization-date>{{POI_ACT_DATE}}</actualization-date>
  {{#INDOOR_PLAN_ID_SECTION}}
  <indoor-plan-id>{{INDOOR_PLAN_ID}}</indoor-plan-id>
  {{/INDOOR_PLAN_ID_SECTION}}
</company>
)";

} // anonymous namespace


CoordsXmlFormatter::CoordsXmlFormatter(std::ostream& out)
    : emitter_(out)
{
    emitter_.Emit("<?xml version='1.0' encoding='UTF-8'?>\n");
    emitter_.Emit("<companies"
                  " xmlns:xi='http://www.w3.org/2001/XInclude'"
                  " version='2.1'>\n");
    ct::StringToTemplateCache(TEMPLATE_KEY, COMPANY_COORDS_XML_TEMPLATE,
                              ct::STRIP_BLANK_LINES);
}

void
CoordsXmlFormatter::append(const PoiDef& poiDef, const LonLatFeedComponent& lonLat)
{
    ct::TemplateDictionary dict(TEMPLATE_KEY);
    dict.SetValue("POI_ID", std::to_string(poiDef.id.get()));
    dict.SetValue(
        "POI_ACT_DATE",
        std::to_string(
            chrono::sinceEpoch<std::chrono::milliseconds>(
                lonLat.actualizationDate()))
    );
    if (!poiDef.permalink.empty()) {
        dict.SetValueAndShowSection("POI_PERMALINK", poiDef.permalink,
                                    "POI_PERMALINK_SECTION");
    }
    dict.SetValue("POI_LAT", std::to_string(lonLat.lat()));
    dict.SetValue("POI_LON", std::to_string(lonLat.lon()));

    if (!poiDef.publishingStatus.empty()) {
        dict.SetValueAndShowSection("POI_PUBLISHING_STATUS", poiDef.publishingStatus,
                                    "POI_PUBLISHING_STATUS_SECTION");
    }

    dumpRubrics(poiDef, dict);
    if (poiDef.indoorPlanId) {
        dict.SetValueAndShowSection("INDOOR_PLAN_ID",
            std::to_string(*poiDef.indoorPlanId),
            "INDOOR_PLAN_ID_SECTION");
    }

    ct::ExpandTemplate(TEMPLATE_KEY, ct::STRIP_BLANK_LINES, &dict,
                       &emitter_);
}

CoordsXmlFormatter::~CoordsXmlFormatter()
{
    emitter_.Emit("</companies>");
}

} // namespace maps::wiki::poi
