#include "plainer.h"
#include <library/cpp/json/json_reader.h>
#include <library/cpp/json/json_writer.h>
#include <util/string/vector.h>

namespace NPrivate {

    TPlainer::TCategory::TCategory(const TString& str)
        : Name(str)
        , NeedValue(str.empty() || str[0] != '@')
    {

    }


    void TPlainer::AddPredInsertRicher(IRicher::TPtr richer) {
        PredInsertRichers.push_back(richer);
    }

    void TPlainer::AddPostInsertRicher(IRicher::TPtr richer) {
        PostInsertRichers.push_back(richer);
    }

    void TPlainer::Process(const NJson::TJsonValue& source, ui32 currentCategory /*= 0*/) {
        if (currentCategory >= Categories.size()) {
            NJson::TJsonValue richSource = source;
            for (const auto& categ : Categories)
                if (categ.NeedValue)
                    richSource.InsertValue(categ.Name, categ.Value);
            for (auto& richer : PredInsertRichers)
                richer->Rich(richSource);
            NJson::TJsonValue* inserted = Inserter->Insert(richSource);
            if (inserted)
                for (auto& richer : PostInsertRichers)
                    richer->Rich(*inserted);
        }
        else if (source.IsMap()) {
            for (const auto& category : source.GetMap()) {
                Categories[currentCategory].Value = category.first;
                Process(category.second, currentCategory + 1);
            }
        }
    }

    TPlainer::TPlainer(IInserter* inserter, const TString& categories)
        : Inserter(inserter)
    {
        for (const auto& categ : SplitString(categories, "."))
            Categories.push_back(TCategory(categ));
    }

    TString JsonToString(const NJson::TJsonValue& json) {
        TString s;
        {
            TStringOutput out(s);
            NJson::WriteJson(&out, &json);
        }
        return s;
    }

    NJson::TJsonValue StringToJson(const TString& s) {
        NJson::TJsonValue result;
        ReadJsonFastTree(s, &result, true);
        return result;
    }
}
