#pragma once
#include <util/generic/vector.h>
#include <util/generic/string.h>
#include <library/cpp/unistat/unistat.h>
#include "time_slide.h"

template <class T>
class TEventsMeter {
private:
    TTimeSlidedHistogram Histogram;

    class TEventsMeterMeta {
    private:
        TVector<TString> SignalNames;
    public:
        void Init(TUnistat& unistat) const {
            for (auto&& i : SignalNames) {
                unistat.DrillFloatHole(i, "dmmm", NUnistat::TPriority(50));
            }
        }

        const TString& GetSignalName(const T value) const {
            return SignalNames[(ui32)value];
        }

        TEventsMeterMeta() {
            for (ui32 i = 0; i < (ui32)T::COUNT; ++i) {
                SignalNames.push_back("events-CTYPE-SERV-" + TypeName<T>() + "-" + ToString(T(i)));
            }
            Init(TUnistat::Instance());
        }
    };

    static TEventsMeterMeta MetaData;

public:
    TEventsMeter(const ui32 segmentsCount, const ui32 secondsDuration)
        : Histogram(segmentsCount, secondsDuration, 0, (ui32)T::COUNT, (ui32)T::COUNT)
    {
    }

    void AddEvent(const T value, const ui32 signalValue = 1) {
        Histogram.Add((ui32)value);
        auto& tass = TUnistat::Instance();
        if (!tass.PushSignalUnsafe(MetaData.GetSignalName(value), signalValue)) {
            DEBUG_LOG << "Not initialized signal: " << MetaData.GetSignalName(value) << Endl;
            tass.PushSignalUnsafe("debug-errors-CTYPE-SERV", 1);
        }
    }

    TVector<ui32> GetState() const {
        return Histogram.Clone();
    }

    NJson::TJsonValue GetReport() const {
        NJson::TJsonValue report(NJson::JSON_MAP);
        TVector<ui32> result = Histogram.Clone();
        CHECK_WITH_LOG(result.size() == (ui32)T::COUNT + 2);
        CHECK_WITH_LOG(result.front() == 0);
        CHECK_WITH_LOG(result.back() == 0);
        for (ui32 i = 1; i < result.size() - 1; ++i) {
            report[ToString(T(i - 1))] = result[i];
        }
        return report;
    }
};

template <class T>
typename TEventsMeter<T>::TEventsMeterMeta TEventsMeter<T>::MetaData;
