#pragma once

#include <saas/util/types/interval.h>
#include <saas/library/sharding/sharding.h>
#include <saas/protos/cluster.pb.h>

namespace NSearchMapParser {
    const ui16 DefaultNehPortShift = 1;
    const ui16 DefaultIndexerPortShift = 2;
    const ui16 DefaultControllerPortShift = 3;

    enum RankType {
        Master /* "master" */,
        Slave /* "slave" */,
        Single /* "single" */
    };

    enum DispatchTarget {
        Distributor /* "distributor" */,
        Backends /* "backends" */,
        Void /* "void" */,
        PersQueue /* "persqueue" */
    };

    struct TSearchInformation {
        TString Name;
        TInterval<TShardIndex> Shards;
        ui16 SearchPort;
        ui16 IndexerPort;
        TString Group;
        TString DC;
        RankType Rank;
        bool DisableSearch;
        bool DisableIndexing;
        bool DisableSearchFiltration;
        bool DisableFetch;
        bool IsSd;

        inline TSearchInformation(const TString& name, ui16 searchPort, ui16 indexerPort,
            RankType rank, TInterval<TShardIndex> originalInterval)
            : Name(name)
            , Shards(originalInterval)
            , SearchPort(searchPort)
            , IndexerPort(indexerPort)
            , Rank(rank)
            , DisableSearch(false)
            , DisableIndexing(false)
            , DisableSearchFiltration(false)
            , DisableFetch(false)
            , IsSd(false)
        {}

        ui32 GetWeight() const {
            if (Rank == NSearchMapParser::Single)
                return 1;
            if (Rank == NSearchMapParser::Master)
                return 2;
            return 0;
        }

        TString GetDescription() const {
            return Name + ":" + ToString(SearchPort);
        }

        TString GetDescriptionForNeh() const {
            return Name + ":" + ToString(GetNehSearchPort());
        }

        ui64 GetNehSearchPort() const {
            return SearchPort + DefaultNehPortShift;
        }

        bool operator<(const TSearchInformation& other) const {
            return Name < other.Name || IndexerPort < other.IndexerPort || SearchPort < other.SearchPort;
        }

        NSaas::TSlotInfo GetSlotInfo(const TString& configType, const TString& service, const TString& serviceType, const TString& ctype) const {
            NSaas::TSlotInfo slotInfo;
            slotInfo.ServiceType = serviceType;
            slotInfo.DisableIndexing = DisableIndexing;
            slotInfo.DisableSearch = DisableSearch;
            slotInfo.DisableSearchFiltration = DisableSearchFiltration;
            slotInfo.DisableFetch = DisableFetch;
            slotInfo.Slot = GetDescription();
            slotInfo.ShardMin = Shards.GetMin();
            slotInfo.ShardMax = Shards.GetMax();
            slotInfo.ConfigType = configType;
            slotInfo.Service = service;
            slotInfo.CType = ctype;
            slotInfo.DC = DC;
            return slotInfo;
        }

        bool Deserialize(const NSaasProto::TRTYSlot& slot);
        NSaasProto::TRTYSlot SerializeToProto() const;
    };

}
