#include "urlhash.h"

#include <saas/protos/rtyserver.pb.h>
#include <library/cpp/logger/global/global.h>

#include <util/digest/city.h>
#include <saas/library/sharding/rules/intervals_enumeration.h>

namespace NSaas {

    TUrlShardingRule::TUrlShardingRule(const TShardsDispatcher::TContext& context)
        : IShardingRule(context)
    {}

    NSearchMapParser::TShardIndex TUrlShardingRule::GetShard(const TStringBuf& url, TKeyPrefix /*kps*/) const {
        Y_ASSERT(url);
        return GetUrlShard(url, Context.GetShardsMax());
    }

    bool TUrlShardingRule::CheckMessage(const NRTYServer::TMessage& message, TString& error) const {
        if (!message.GetDocument().HasUrl()) {
            error = "Document doesn't have url";
            return false;
        }
        return true;
    }

    NSearchMapParser::TShardIndex TUrlShardingRule::GetUrlShard(const TStringBuf& url, const NSearchMapParser::TShardIndex shards) {
        ui64 hash = CityHash64(url);
        NSearchMapParser::TShardIndex shard = static_cast<NSearchMapParser::TShardIndex>(hash) % shards;
        return shard;
    }

    bool TUrlShardingRule::CheckSearchInterval(TStringBuf url, TKeyPrefix /*kps*/, const TInterval<NSearchMapParser::TShardIndex>& interval) const {
        if (url.empty()) {
            return true;
        }

        const NSearchMapParser::TShardIndex shard = GetUrlShard(url, Context.GetShardsMax());
        return CheckInterval(shard, interval);
    }

    void TUrlShardingRule::EnumerateIntervals(TStringBuf url, TKeyPrefix /*kps*/, const TShardIntervals& sortedIntervals,
                                              IShardIntervalCallback& callback) const {
        const auto shardMax = Context.GetShardsMax();
        auto shardIndex = GetUrlShard(url, shardMax);
        NSaas::UrlEnumeration::EnumerateIntervals(shardIndex, sortedIntervals, callback);
    }

    TShardsDispatcher::IShardingRule::TFactory::TRegistrator<TUrlShardingRule> TUrlShardingRule::Registrator(UrlHash);
}
