#include "signals.h"
#include <saas/indexerproxy/configs/config.h>

#include <saas/library/behaviour/behaviour.h>
#include <library/cpp/http/misc/httpcodes.h>
#include <library/cpp/logger/global/global.h>
#include <util/string/cast.h>
#include <util/string/join.h>
#include <util/system/datetime.h>

constexpr TStringBuf SignalsPrefix = "saaspush";

TSaasPushSignals::TSaasPushSignals() {
    for (auto code : GetDispCodes()) {
        Codes.insert(ToString(code));
        Codes.insert(ToString(code).substr(0, 1) + "xx");
        Codes.insert("all");
    }
}

void TSaasPushSignals::BuildSignals(const TSet<TString>& services) {
    TSaasPushSignals signals;
    for (const auto& i : services) {
        signals.AddService(i);
    }

    signals.Init(TUnistat::Instance());
}

void TSaasPushSignals::Init(TUnistat& t) const {
    static const TVector<double> intervals = { 0, 1, 2, 3, 4, 5, 10, 15, 20, 25, 30,
        40, 50, 60, 70, 80, 90, 100, 125, 150, 175, 200, 225, 250, 300, 350, 400,
        500, 600, 700, 800, 900, 1000, 1500, 2000, 3000, 5000, 10000 };

    t.DrillFloatHole(Join("-", SignalsPrefix, "incorrect-state"), "ammx", Prio("", false), NUnistat::TStartValue(0), EAggregationType::LastValue, true);

    for (auto code : Codes) {
        t.DrillFloatHole(Join("-", SignalsPrefix, code), "dmmm", Prio(code, false));
    }

    t.DrillHistogramHole(Join("-", SignalsPrefix, "times"), "dhhh", Prio("", true), intervals);
    for (auto service : Services) {
        for (auto code : Codes) {
            t.DrillFloatHole(Join("-", SignalsPrefix, service, code), "dmmm", Prio(code, true, true));
        }
        t.DrillHistogramHole(Join("-", SignalsPrefix, "times", service), "dhhh", Prio("", true), intervals);
    }
}

void TSaasPushSignals::InIncorrectState(bool value) {
    TUnistat& inst = TUnistat::Instance();
    PushSignal(inst, Join("-", SignalsPrefix, "incorrect-state"), value ? 1 : 0);
}

void TSaasPushSignals::ProcessedDoc(ui32 code, TDuration processTime, TStringBuf service) {
    TUnistat& inst = TUnistat::Instance();

    TString codeString = ToString(code);
    TString xxCode = codeString.substr(0, 1) + "xx";

    PushSignalWithCode(inst, Join("-", SignalsPrefix, ""), codeString, xxCode);

    PushSignal(inst, Join("-", SignalsPrefix, "all"), 1);
    if (service) {
        PushSignalWithCode(inst, Join("-", SignalsPrefix, service, ""), codeString, xxCode);
        PushSignal(inst, Join("-", SignalsPrefix, service, "all"), 1);
    }

    if (code == 200) {
        PushSignal(inst, Join("-", SignalsPrefix, "times"), processTime.Seconds());
        PushSignal(inst, Join("-", SignalsPrefix, "times", service), processTime.Seconds());
    }
}
