#pragma once

#include "script.h"
#include "scripts_helper.h"

#include <saas/deploy_manager/scripts/common/get_slots_info/get_slots_used_free.h>
#include <saas/deploy_manager/server/client/client.h>
#include <saas/deploy_manager/modules/resources/resources.h>
#include <saas/library/searchmap/searchmap.h>
#include <saas/library/searchmap/parsers/json/json.h>
#include <util/system/mutex.h>

namespace NRTYDeploy {

    class TScriptTagSlots: public IScript {
        static TFactory::TRegistrator<TScriptTagSlots> Registrator;
    public:

        virtual TString Help() override {
            return "You have to get name of tag. You can receive slots, included in the tag";
        }

        virtual bool Process(IDeployInfoRequest& request) override {
            const TString tag = request.GetRD().CgiParam.Get("tag");

            TTagsInfo::TTag tagInfo(tag);

            NRTYCluster::TCluster cluster;
            //todo: use_containers param (false by default, real hosts are need for ssm)
            if (request.GetResourcesManager().GetSlotList(tagInfo, "TEST", false, TVector<NRTYCluster::TSlotData>(), cluster)) {
                auto mapSlots = cluster.GetCTypeCluster();
                TString replyStr = NJson::WriteJson(mapSlots["TEST"].Serialize());
                request.Output() << "HTTP/1.1 200 \r\n\r\n";
                request.Output() << replyStr << Endl;
            } else {
                request.Output() << "HTTP/1.1 400 \r\n\r\n";
                request.Output() << "Can't do it. See help." << Endl;
                return false;
            }
            return true;
        }
    };

    class TScriptAvailableSlots: public IScript {
        static TFactory::TRegistrator<TScriptAvailableSlots> Registrator;
    public:
        virtual TString Help() override {
            return "You have to get CType, ServiceType, ServiceName. You can receive slots, that available for this service";
        }

        virtual bool Process(IDeployInfoRequest& request) override {
            TClusterTask::TCgiContext context = TClusterTask::TCgiContext::Parse(request.GetRD().CgiParam);
            if (context.Service == "")
                context.Service = "*";
            NRTYCluster::TCluster cluster;
            if (request.GetResourcesManager().GetAvailableSlotsForService(context.CType, context.ServiceType, context.Service, cluster)) {
                request.Output() << "HTTP/1.1 200 \r\n\r\n";
                request.Output() << NJson::WriteJson(cluster.Serialize()) << Endl;
            } else {
                request.Output() << "HTTP/1.1 400 \r\n\r\n";
                request.Output() << "Can't do it. See help." << Endl;
                return false;
            }
            return true;
        }
    };

    class TScriptFreeSlots: public IScript {
        static TFactory::TRegistrator<TScriptFreeSlots> Registrator;
    public:
        virtual TString Help() override {
            return "You have to get CType, ServiceType, ServiceName. You can receive slots, that available for extend this service";
        }

        virtual bool Process(IDeployInfoRequest& request) override {
            TClusterTask::TCgiContext context = TClusterTask::TCgiContext::Parse(request.GetRD().CgiParam);
            if (context.Service == "")
                context.Service = "*";
            NRTYCluster::TCluster cluster;
            if (GetFreeSlotsForService(context.CType, context.ServiceType, context.Service, request, cluster)) {
                request.Output() << "HTTP/1.1 200 \r\n\r\n";
                request.Output() << NJson::WriteJson(cluster.Serialize()) << Endl;
            } else {
                request.Output() << "HTTP/1.1 400 \r\n\r\n";
                request.Output() << "Can't do it. See help." << Endl;
                return false;
            }
            return true;
        }
    };

    class TScriptUsingSlots: public IScript {
        static TFactory::TRegistrator<TScriptUsingSlots> Registrator;
    public:
        virtual TString Help() override {
            return "You have to get CType, ServiceType, ServiceName. You can receive slots, that using for this service";
        }

        virtual bool Process(IDeployInfoRequest& request) override {
            TClusterTask::TCgiContext context = TClusterTask::TCgiContext::Parse(request.GetRD().CgiParam);
            if (context.Service == "")
                context.Service = "*";
            NRTYCluster::TCluster cluster;
            TVector<NSearchMapParser::TSearchMapHost> slots;
            NJson::TJsonValue reply;
            reply[context.CType] = NJson::TJsonValue(NJson::JSON_MAP);
            NJson::TJsonValue& replyByCType = reply[context.CType];

            if (!GetUsingServiceSlots(context.CType, context.ServiceType, context.Service, request, slots)) {
                request.Output() << "HTTP/1.1 400 \r\n\r\n";
                request.Output() << "Can't do it. See help.";
                return false;
            }

            for (auto&& i : slots) {
                NRTYCluster::TSlotData sd;
                if (NRTYCluster::TSlotData::Parse(i.GetSlotName(), sd)) {
                    replyByCType[sd.GetDC()].AppendValue(NSearchMapParser::TJsonSearchMapParser::SerializeHost(i, true));
                } else {
                    replyByCType["unknown"].AppendValue(NSearchMapParser::TJsonSearchMapParser::SerializeHost(i, true));
                }
            }
            TString replyStr = NJson::WriteJson(reply);
            request.Output() << "HTTP/1.1 200 \r\n\r\n";
            request.Output() << replyStr;
            return true;
        }
    };
}
