#include "deploy_metaservice_builder.h"
#include <saas/deploy_manager/scripts/common/global_names/global_names.h>
#include <library/cpp/json/json_reader.h>

namespace NRTYDeployInfo {

    TMetaserviceDeployComponentInfo::TFactory::TRegistrator<TMetaserviceDeployComponentInfo> TMetaserviceDeployComponentInfo::Registrator(META_SERVICE_SERVICE);
    TMetaserviceDeployBuilder::TFactory::TRegistrator<TMetaserviceDeployBuilder> TMetaserviceDeployBuilder::Registrator(META_SERVICE_SERVICE);

    NSearchMapParser::TSearchMap TMetaserviceDeployComponentInfo::DoSearchMap(const TString& service) const {
        const NSearchMapParser::TSearchMap& sm = SearchMap();
        NSearchMapParser::TSearchMap result;
        const NSearchMapParser::TSearchMapService* servicePtr = sm.GetService(service);
        if (servicePtr) {
            result.AddService(service) = *servicePtr;
            for (const auto& metaService : sm.GetMetaServices())
                if (metaService.Name == service)
                    result.GetMetaServices().push_back(metaService);
        }
        return result;
    }

    const NSearchMapParser::TSearchMap& TMetaserviceDeployComponentInfo::SearchMap() const {
        const NSaas::TClusterConst* clusterPtr = NSaas::TClusterLocker::DefineConst(*GetCommon(), GetCType());
        if (!clusterPtr) {
            ythrow yexception() << "Incorrect cluster info for " << GetCType();
        }
        return clusterPtr->MetaServiceSearchMap();
    }

    NSearchMapParser::TSearchMap TMetaserviceDeployComponentInfo::DoSearchMapBySlot(const TString&, const NSaas::TClusterConst* clusterPtr, const TString&) const {
        return clusterPtr->MetaServiceSearchMap();
    }

    TString TMetaserviceDeployComponentInfo::GetComponentName() const {
        return META_SERVICE_SERVICE;
    }

    bool TMetaserviceDeployBuilder::DoBuildFilesInfo(const NRTYDeploy::TFileContentGenerator::TContext& context, TStringStream& /*errors*/, bool /*forcedOnly*/) {
        NRTYDeploy::TFileContentGenerator::AddGenerators(Nodes, *GetCommon(), GetConfigsPath(), "", context.SlotInfo);
        return true;
    }

    void TMetaserviceDeployBuilder::AddService(NSaas::TCluster& cluster) {
        NSearchMapParser::TMetaService ms;
        ms.Name = Service;
        cluster.AddMetaService(ms);
    }

    void TMetaserviceDeployBuilder::EditService(NSaas::TCluster& cluster, const NJson::TJsonValue& serviceJson) {
        NSearchMapParser::TMetaService* metaservice = cluster.MutableMetaService(Service);
        if (!metaservice) {
            ythrow yexception() << "Incorrect service name: " << Service;
        }
        NSearchMapParser::TMetaService copy;
        if (!copy.Deserialize(serviceJson))
            ythrow yexception() << "errors while deserialize service";
        *metaservice = copy;
    }

    void TMetaserviceDeployBuilder::CopyService(NSaas::TCluster& cluster, const TString& newName, const bool /*clearReplicas*/) {
        if(cluster.IsMetaServiceExist(newName)) {
            ythrow yexception() << "Metaservice with name " << newName << " already exists";
        }

        NSearchMapParser::TMetaService* metaservice = cluster.MutableMetaService(Service);
        if (!metaservice)
            ythrow yexception() << "Incorrect service name: " << Service;
        NSearchMapParser::TMetaService newService = *metaservice;
        newService.Name = newName;
        cluster.AddMetaService(newService);
    }

    bool TMetaserviceDeployBuilder::RemoveService(NSaas::TCluster& cluster) {
        return cluster.RemoveMetaservice(Service);
    }

}
