#include "nanny.h"
#include "request_executor.h"
#include <saas/util/cluster/datacenter.h>
#include <saas/deploy_manager/config/config.h>

TNannyModule::TNannyModule(const TDeployManagerConfig::TNannyConfig& nannyConfig)
    : NannyConfig(nannyConfig)
{}

bool TNannyModule::GetSlots(const TString& tag, const bool useContainerNames, TVector<NRTYCluster::TSlotData>& slotsResult) {
    if (!NannyConfig.IsInitialized())
        return false;

    TGetSlotsRequest request(NannyConfig, tag, useContainerNames);

    int minutes = Now().Minutes();

    if (NannyConfig.CacheTestMode || NeedFallbackToCache(minutes)) {
        bool resultFromCache = request.GetFromCache();
        slotsResult = request.GetResult();
        return resultFromCache;
    }
    bool isFatalError = false;
    bool result = TNannyRequestExecutor(NannyConfig).ExecuteRequest(request, isFatalError, 2);
    bool gotFromCache = false;

    if (!result) {
        result = request.GetFromCache();
        gotFromCache = true;
    }
    if (!result) {
        result = TNannyRequestExecutor(NannyConfig).ExecuteRequest(request, isFatalError, 8);
    }
    if (result && !gotFromCache) {
        request.PutToCache();
    }

    slotsResult = request.GetResult();
    if (isFatalError) {
        AtomicIncrement(FatalFailsCount);
        AtomicSet(LastErrorMinutes, minutes);
        ERROR_LOG << "Nanny errors count=" << FatalFailsCount << Endl;
    }
    return result;
}

bool TNannyModule::NeedFallbackToCache(const int nowMinutes) {
    if (nowMinutes - AtomicGet(LastErrorMinutes) < NannyConfig.CacheFallbackUndoMinutes) {
        return AtomicGet(FatalFailsCount) > NannyConfig.CacheFallbackErrorsCnt;
    } else {
        AtomicSet(FatalFailsCount, 0);
        return false;
    }
}

bool TNannyModule::GetRuntimeAttrs(const TString& tag, NJson::TJsonValue& files) const {
    if (!NannyConfig.IsInitialized())
        return false;

    TGetRuntimeAttrsRequest request(NannyConfig, tag);

    bool isFatalError = false;
    bool result = TNannyRequestExecutor(NannyConfig).ExecuteRequest(request, isFatalError);

    files = request.GetResult();
    return result;
}
