#include "script.h"
#include <saas/deploy_manager/meta/cluster.h>
#include <saas/deploy_manager/server/client/client.h>
#include <saas/deploy_manager/scripts/check_slots/task/task.h>
#include <saas/deploy_manager/scripts/common/scripts_helper.h>
#include <saas/util/cluster/cluster.h>
#include <dict/dictutil/str.h>

namespace NRTYDeploy {

    bool TScriptCopyService::Process(IDeployInfoRequest& request) {
        const TCgiParameters& cgi = request.GetRD().CgiParam;
        const TString& from = cgi.Get("from");
        const TString& to = cgi.Get("to");
        const TString& ctype = cgi.Get("from_ctype");

        if (!!ctype) {
            NSaas::TClusterLocker clusterPtr = NSaas::TClusterLocker::DefineMutable(request, ctype);
            if (!clusterPtr) {
                request.Output() << "HTTP/1.1 500 \r\n\r\n";
                request.Output() << "Resource " << "/common/" << ctype << "/cluster.meta is not available for modification";
                return false;
            }

            NSearchMapParser::TSearchMapService* serviceInfoFrom = clusterPtr->ServiceSearchMap(from);
            NSearchMapParser::TSearchMapService* serviceInfoTo = clusterPtr->AddRTYService(to);
            if (serviceInfoFrom && serviceInfoTo) {
                serviceInfoTo->IndexingTarget = serviceInfoFrom->IndexingTarget;
                serviceInfoTo->ShardsDispatcher = serviceInfoFrom->ShardsDispatcher;
                SetData(clusterPtr.GetContent(), "");
                TString errorMessage;
                if (!clusterPtr->Validate(errorMessage)) {
                    DEBUG_LOG << "Can't store cluster meta: " << errorMessage << Endl;
                    request.Output() << "HTTP/1.1 400 \r\n\r\n";
                    request.Output() << "Incorrect new cluster: " << errorMessage;
                    return false;
                }
                SetData("", clusterPtr.GetContent());
                if (!clusterPtr.Save()) {
                    request.Output() << "HTTP/1.1 500 \r\n\r\n";
                    request.Output() << "Incorrect storage structure";
                    return false;
                }
            }
        }

        TVector<TString> nodes;
        if (!request.GetCommonData().GetStorage().GetNodes("/configs/" + from, nodes)) {
            request.Output() << "HTTP/1.1 400 \r\n\r\n";
            request.Output() << "incorrect source service name: " << from << Endl;
            return true;
        }

        for (auto&& i : nodes) {
            TString value;
            if (request.GetCommonData().GetStorage().GetValue("/configs/" + from + "/" + i, value)) {
                TString newName = i;
                ReplaceAll(newName, from.data(), to.data());
                ReplaceAll(value, from.data(), to.data());
                request.GetCommonData().GetStorage().SetValue("/configs/" + to + "/" + newName, value);
            }
        }

        request.Output() << "HTTP/1.1 200 \r\n\r\n";
        request.Output() << "OK";
        return true;
    }

    IScript::TFactory::TRegistrator<TScriptCopyService> TScriptCopyService::Registrator("copy_service");
}
