#include "searchmap.h"
#include <saas/deploy_manager/meta/cluster.h>
#include <saas/deploy_manager/scripts/common/deploy/deploy_builder.h>
#include <library/cpp/logger/global/global.h>
#include <saas/library/searchmap/parsers/json/json.h>

#define SEARCHMAP_FILE_CONTENT_GENERATOR_TYPE "searchmap"
#define SEARCHMAP_FILE "searchmap.json"

namespace NRTYDeploy {
    TSearchMapContentGenerator::TSearchMapContentGenerator()
        : Version(-1)
    {}

    TSearchMapContentGenerator::TSearchMapContentGenerator(const ICommonData& data, const TString& ctype, const TString& serviceType, i64 version)
        : Version(version)
        , ServiceType(serviceType)
    {
        if (Version == -1)
            NSaas::TClusterLocker::GetVersion(data, ctype, Version);
    }

    TString TSearchMapContentGenerator::GetType() const {
        return SEARCHMAP_FILE_CONTENT_GENERATOR_TYPE;
    }

    TString TSearchMapContentGenerator::GetRename(const TFileContentGenerator::TContext& /*context*/) const {
        return SEARCHMAP_FILE;
    }

    void TSearchMapContentGenerator::Serialize(NJson::TJsonValue& json) const {
        TFileContentGenerator::Serialize(json);
        json.InsertValue("version", Version);
        json.InsertValue("service_type", ServiceType);
    }

    void TSearchMapContentGenerator::DoDeserialize(const NJson::TJsonValue& json) {
        NRTYDeploy::TFileContentGenerator::DoDeserialize(json);
        TFileContentGenerator::DoDeserialize(json);
        Version = json["version"].GetIntegerRobust();
        ServiceType = json["service_type"].GetStringRobust();
    }

    void TSearchMapContentGenerator::SetLastVersion() {
        Version = -1;
    }

    bool TSearchMapContentGenerator::DoGetContent(TString& result, const ICommonData& common, const TFileContentGenerator::TContext& context) const {
        const NSaas::TClusterConst* locker = NSaas::TClusterLocker::DefineConst(common, context.SlotInfo.CType, Version);
        if (!locker) {
            ERROR_LOG << "Incorrect cluster info" << Endl;
            return false;
        }
        DEBUG_LOG << "Source Cluster:\n" << locker->GetCluster().Serialize() << Endl;

        NRTYDeployInfo::IDeployComponentInfo::TPtr info = NRTYDeployInfo::IDeployComponentInfo::TFactory::Construct(ServiceType);
        CHECK_WITH_LOG(!!info);
        info->SetInfo(&common, context.SlotInfo.CType);

        auto ism = info->SearchMapBySlot(context.SlotInfo.Slot, locker, context.SlotInfo.DC);

        NSearchMapParser::TJsonSearchMapParser jsmp(ism);

        result = jsmp.SerializeToString();
        DEBUG_LOG << "Return " << SEARCHMAP_FILE << " for " << context.SlotInfo.Slot << "/" << context.SlotInfo.Service << ":\n" << result << Endl;
        return true;
    }

    TString TSearchMapContentGenerator::GetCacheKey(const TContext& context) const {
        MD5 calc;
        calc.Update(context.SlotInfo.CType.data(), context.SlotInfo.CType.size());
        calc.Update(context.SlotInfo.ServiceType.data(), context.SlotInfo.ServiceType.size());
        NRTYDeployInfo::IDeployComponentInfo::TPtr info = NRTYDeployInfo::IDeployComponentInfo::TFactory::Construct(ServiceType);
        CHECK_WITH_LOG(!!info);
        TString slotKey = info->GetSearchMapBySlotKey(context.SlotInfo.Slot, context.SlotInfo.DC);
        calc.Update(slotKey.data(), slotKey.size());
        char buf[33];
        return calc.End(buf);
    }

    TSearchMapContentGenerator::TFactory::TRegistrator<TSearchMapContentGenerator> TSearchMapContentGenerator::Registrator(SEARCHMAP_FILE_CONTENT_GENERATOR_TYPE);
}
