#include "histogram.h"

#include <saas/library/histogram/histogram.h>

#include <util/folder/path.h>
#include <util/generic/map.h>

NRTYServer::THistogramProcessor::THistogramProcessor(const TEntities& entities, const TString& outputDir)
    : Entities(entities)
    , OutputDirectory(outputDir)
{
    for (auto&& entity : Entities) {
        if (Tuples.GetFullTuplesSet().contains(entity.TupleName)) {
            throw yexception() << "histogram for " << entity.TupleName << " is calculated twice";
        }

        Tuples.AddInfo(NOxygen::TTupleUsageInfo().AddTuple(entity.TupleName).SetRequired(false));
    }
    Values.resize(Entities.size());
}

void NRTYServer::THistogramProcessor::Start() {
}

NThreading::TFuture<NOxygen::TReturnObjectContext> NRTYServer::THistogramProcessor::Process(NOxygen::TObjectContext objectContext, ui32 tmpObjectId) {
    for (size_t i = 0; i < Entities.size(); ++i) {
        if (Values[i].size() <= tmpObjectId) {
            Values[i].resize(tmpObjectId + 1);
        }
        Values[i][tmpObjectId] = objectContext.GetOrElse<ui64>(Entities[i].TupleName, 0);
    }
    return NOxygen::TReturnObjectContext::FutureOk;
}

void NRTYServer::THistogramProcessor::Finish(const NOxygen::TDocIdMap* map) {
    auto deleted = [map](ui32 id) {
        return map && (map->Map(id) == NOxygen::TDocIdMap::DeletedDocument());
    };

    NRTYServer::THistograms histograms;
    for (size_t i = 0; i < Entities.size(); ++i) {
        const TEntity& entity = Entities[i];
        auto& h = histograms.AddAttribute(entity.TupleName, entity.Period);
        for (ui32 tmpObjectId = 0; tmpObjectId < Values[i].size(); ++tmpObjectId) {
            if (!deleted(tmpObjectId)) {
                h.Add(Values[i][tmpObjectId]);
            }
        }
    }
    histograms.Serialize(TFsPath(OutputDirectory) / "indexhistogram");
}
