#pragma once

#include <library/cpp/charset/doccodes.h>
#include <util/generic/hash.h>
#include <util/generic/list.h>
#include <util/generic/singleton.h>
#include <util/stream/str.h>
#include <util/string/vector.h>
#include <library/cpp/html/face/parstypes.h>
#include <library/cpp/mime/types/mime.h>

namespace NRTYServer {
    class TZone;
}

class TCustomDocumentGenerator {
public:
    struct TResult {
        TStringStream Body;
        TStringStream ParserConfig;
        MimeTypes MimeType;
    };

    struct TOptions {
        bool PreserveNames = false;
    };

public:
    TCustomDocumentGenerator(const TOptions& options);
    const TResult& GetResult() const {return Result;}
    void AddZone(const TString& name);
    void AddZoneAttribute(const TString& name, const TString& value, ATTR_TYPE type);
    void AddText(const TString& text);
    void EndZone();
    void Finish();

private:
    struct TZoneAttr {
        TString Descr;
        TVector<TString> Elements;
    };

private:
    void CloseHeader();
    void GenerateConfig();

    TString GetZoneName(const TString& base);
    TString GetAttributeName(const TString& base);

private:
    const TOptions Options;

    TResult Result;
    THashMap<TString, TVector<TString>> ConfigZones;
    THashMap<TString, TZoneAttr> ConfigZoneAttrs;
    TList<TString> Tags;
    ui64 Counter;
    bool HeaderOpened;
};

class TZoneParser: public TCustomDocumentGenerator {
public:
    TZoneParser(const NRTYServer::TZone& zone, const TOptions& options = Default<TOptions>())
        : TCustomDocumentGenerator(options)
    {
        ParseZone(zone);
        Finish();
    }

private:
    void ParseZone(const NRTYServer::TZone& zone);
};
