#include "relev_work_helper.h"
#include <saas/deploy_manager/scripts/common/deploy/deploy_builder.h>
#include <saas/deploy_manager/scripts/common/file_content_generators/common.h>
#include <saas/deploy_manager/scripts/common/global_names/global_names.h>
#include <saas/deploy_manager/server/client/client.h>

namespace {
    inline bool IsRelevConfName(const TString& fileName) {
        return fileName.StartsWith("relev.conf");
    }

    inline bool IsDefaultRelevConfName(const TString& fileName) {
        return fileName.StartsWith("text-relev-num");
    }
}

namespace NRTYDeploy {

    TString TRelevWorkHelper::LoadRelveConfig(ICommonData& commonData, const TFsPath& path) {
        TString data;
        TVector<TString> files;
        if (!commonData.GetStorage().GetNodes(path, files))
            ythrow TCodedException(500) << "cannot list " << path;
        for (const auto& file : files) {
            if (IsRelevConfName(TFsPath(file).GetName())) {
                if (!commonData.GetStorage().GetValue(path / file, data))
                    ythrow TCodedException(500) << "cannot get data from " << file;
                break;
            }
        }
        if (!data) {
            for (const auto& file : files) {
                if (IsDefaultRelevConfName(TFsPath(file).GetName())) {
                    if (!commonData.GetStorage().GetValue(path / file, data))
                        ythrow TCodedException(500) << "cannot get data from " << file;
                    break;
                }
            }
        }
        return data;
    }

    void TRelevWorkHelper::LoadFactors(ICommonData& commonData, const TString& service, const TString& ctype) {
        if (!service)
            return;
        NRTYDeployInfo::IDeployComponentInfo::TPtr component(NRTYDeployInfo::IDeployComponentInfo::TFactory::Construct(RTYSERVER_SERVICE));
        component->SetInfo(&commonData, ctype);
        NRTYDeployInfo::IDeployServiceInfo::TPtr builder = component->BuildServiceInfo(service);
        TString data;
        if (!ctype) {
            TVector<TString> files;
            try {
                data = LoadRelveConfig(commonData, builder->GetConfigsPath());
            } catch (...) {
                WARNING_LOG << "Error while load factors for " << service << ", " << ctype << ": " << CurrentExceptionMessage() << Endl;
                data = LoadRelveConfig(commonData, "/common");
            }
        } else {
            TFileContentGenerator::TContext context;
            context.SlotInfo.CType = ctype;
            context.SlotInfo.Service = service;
            context.SlotInfo.ServiceType = RTYSERVER_SERVICE;
            TStringStream errors;
            if (!builder->BuildFilesInfo(context, errors, "CURRENT"))
                ythrow TCodedException(500) << "error while build files info: " << errors.Str();
            for (const auto& file : builder->GetNodes()) {
                if (IsRelevConfName(TFsPath(file->GetRename(context)).GetName())) {
                    if (!file->GetContent(data, commonData, context))
                        ythrow TCodedException(500) << "cannot get data from " << file->GetRename(context);
                    break;
                }
            }
            if (!data) {
                for (const auto& file : builder->GetNodes()) {
                    if (IsDefaultRelevConfName(TFsPath(file->GetRename(context)).GetName())) {
                        if (!file->GetContent(data, commonData, context))
                            ythrow TCodedException(500) << "cannot get data from " << file->GetRename(context);
                    }
                }
            }
        }
        if (!data)
            ythrow yexception() << "do not know how to get info about relev config for service " << service << ", " << ctype;
        LoadFactors(data);
    }

    void TRelevWorkHelper::LoadFactors(const TString& config) {
        TStringInput si(config);
        NJson::TJsonValue relevJson;
        if (!NJson::ReadJsonTree(&si, &relevJson))
            return;
        LoadFactors(relevJson["static_factors"]);
        LoadFactors(relevJson["dynamic_factors"]);
        LoadFactors(relevJson["rty_dynamic_factors"]);
        LoadFactors(relevJson["suggest_factors"]);
        LoadFactors(relevJson["user_factors"]);
        LoadFactors(relevJson["zone_factors"]);
    }

    void TRelevWorkHelper::LoadFactors(const NJson::TJsonValue& factorsSet) {
        for (const auto& f : factorsSet.GetMap()) {
            ui32 index;
            if (f.second.IsUInteger())
                index = f.second.GetUIntegerRobust();
            else
                index = f.second["index"].GetUIntegerRobust();
            IndexByName[f.first] = index;
            NameByIndex[index] = f.first;
        }
    }

}
