#include "indoor_names_formatter.h"

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

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

using namespace std::string_literals;

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

const char INDOOR_COMPANY_NAMES_XML_TEMPLATE[] = R"(
{{%AUTOESCAPE context="XML"}}
<company>
  <company-id>{{POI_ID}}</company-id>

  {{#ONE_POI_NAME}}
  <name lang="{{POI_NAME_LANG}}">{{POI_NAME_VALUE}}</name>
  {{/ONE_POI_NAME}}

  {{#ONE_POI_SHORT_NAME}}
  <shortname lang="{{POI_NAME_LANG}}">{{POI_NAME_VALUE}}</shortname>
  {{/ONE_POI_SHORT_NAME}}

  {{#ONE_POI_SYNONYM_NAME}}
  <synonym lang="{{POI_NAME_LANG}}">{{POI_NAME_VALUE}}</synonym>
  {{/ONE_POI_SYNONYM_NAME}}

  {{#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>

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

  <indoor-level-universal>{{POI_INDOOR_LEVEL_UNIVERSAL}}</indoor-level-universal>
</company>
)";

} // anonymous namespace


IndoorNamesXmlFormatter::IndoorNamesXmlFormatter(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, INDOOR_COMPANY_NAMES_XML_TEMPLATE,
                              ct::STRIP_BLANK_LINES);
}

void
IndoorNamesXmlFormatter::append(const PoiDef& poiDef, const NamesFeedComponent& names)
{
    ct::TemplateDictionary dict(TEMPLATE_KEY);
    REQUIRE(poiDef.id, "unspecified POI_ID");
    dict.SetValue("POI_ID", std::to_string(poiDef.id.get()));
    REQUIRE(poiDef.actualizationDate, "unspecified POI_ACT_DATE");
    dict.SetValue(
        "POI_ACT_DATE",
        std::to_string(chrono::sinceEpoch<std::chrono::milliseconds>(poiDef.actualizationDate.get()))
    );
    dumpRubrics(poiDef, dict);
    for (const auto& name : names.names()) {
        auto* nameTemplate = dict.AddSectionDictionary("ONE_POI_NAME");
        nameTemplate->SetValue("POI_NAME_LANG", name.lang);
        nameTemplate->SetValue("POI_NAME_VALUE", name.value);
    }
    for (const auto& name : names.shortNames()) {
        auto* nameTemplate
            = dict.AddSectionDictionary("ONE_POI_SHORT_NAME");
        nameTemplate->SetValue("POI_NAME_LANG", name.lang);
        nameTemplate->SetValue("POI_NAME_VALUE", name.value);
    }
    for (const auto& name : names.synonymNames()) {
        auto* nameTemplate
            = dict.AddSectionDictionary("ONE_POI_SYNONYM_NAME");
        nameTemplate->SetValue("POI_NAME_LANG", name.lang);
        nameTemplate->SetValue("POI_NAME_VALUE", name.value);
    }
    if (!poiDef.permalink.empty()) {
        dict.SetValueAndShowSection("POI_PERMALINK", poiDef.permalink,
                                    "POI_PERMALINK_SECTION");
    }
    REQUIRE(!poiDef.indoorLevelUniversal.empty(),
        "Formatter is for indoor poi only.");
    dict.SetValue("POI_INDOOR_LEVEL_UNIVERSAL", poiDef.indoorLevelUniversal);
    ct::ExpandTemplate(TEMPLATE_KEY, ct::STRIP_BLANK_LINES, &dict,
                       &emitter_);
}

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

} // namespace maps::wiki::poi:

