#pragma once

#include "algorithm.h"
#include <library/cpp/json/json_value.h>
#include <util/generic/string.h>
#include <util/generic/set.h>
#include <util/generic/hash.h>
#include <util/generic/ptr.h>

namespace NPrivate {

    class TStatisticsField : public TSimpleRefCount <TStatisticsField> {
    public:
        typedef TIntrusivePtr<TStatisticsField> TPtr;

        TStatisticsField(const TString& valuePath, const TString& caption);
        virtual ~TStatisticsField() {}
        virtual void UpdateValue(const NJson::TJsonValue& value) = 0;
        virtual ui64 GetValue() const = 0;
        const TString& GetCaption() const {
            return Caption;
        }
        const TSet<TString>& GetValuePath() const {
            return ValuePath;
        }
        void AddValuePath(const TString& valuePath) {
            ValuePath.insert(valuePath);
        }

    protected:
        TSet<TString> ValuePath;
        TString Caption;
    };

    class TStatisticsFieldOneParam : public TStatisticsField {
    public:
        TStatisticsFieldOneParam(const TString& valuePath, const TString& caption);
        virtual void UpdateValue(const NJson::TJsonValue& value) override;
        virtual ui64 GetValue() const override;

    protected:
        virtual void DoUpdateValue(ui64 value) = 0;
        ui64 Value;
    };

    class TStatisticsFieldSum : public TStatisticsFieldOneParam {
    public:
        TStatisticsFieldSum(const TString& valuePath, const TString& caption);

    protected:
        virtual void DoUpdateValue(ui64 value) override;
    };

    class TStatisticsFieldGroupedSet : public TStatisticsField {
    public:
        TStatisticsFieldGroupedSet(const TString& valuePath, const TString& caption, const TString& groupBy);
        virtual void UpdateValue(const NJson::TJsonValue& value) override;
        virtual ui64 GetValue() const override;

    private:
        typedef THashMap<TString, TCountByValue> TGroupedValues;

    private:
        TString GroupBy;
        TGroupedValues Values;
    };

}
