#pragma once
#include <saas/library/sharding/sharding.h>
#include <saas/library/searchmap/searchmap.h>

#include <saas/util/cluster/cluster.h>
#include <saas/util/types/interval.h>

#include <util/generic/vector.h>

namespace NRTYReplication {

    struct TIntervalLink {
        NSearchMapParser::TShardsInterval Interval;
        NSearchMapParser::TSearchMapHost Restore;
        const NSearchMapParser::TSearchMapHost* Donor;

        TIntervalLink(const NSearchMapParser::TSearchMapHost& restore) {
            Restore = restore;
            Donor = nullptr;
            Interval = Restore.Shards;
        }

        TIntervalLink(const NSearchMapParser::TSearchMapHost& restore, NSearchMapParser::TShardIndex smin, NSearchMapParser::TShardIndex smax, const NSearchMapParser::TSearchMapHost* donor) {
            Restore = restore;
            Donor = donor;
            Interval = NSearchMapParser::TShardsInterval(smin, smax);
        }
    };

    class TDonorsBuilder {
    private:
        TVector<NSearchMapParser::TSearchMapHost> RestoreSlots;
        TVector<NSearchMapParser::TSearchMapHost> UsefulSlots;
        TVector<TIntervalLink> Intervals;

        void AddDownloadInfo(const NSearchMapParser::TSearchMapHost& restore, const NSearchMapParser::TSearchMapHost& donor);
        TString Print() const;

    public:

        typedef TAtomicSharedPtr<TDonorsBuilder> TPtr;

        const TVector<NSearchMapParser::TSearchMapHost>& GetRestore() const {
            return RestoreSlots;
        }

        const TVector<NSearchMapParser::TSearchMapHost>& GetDonors() const {
            return UsefulSlots;
        }

        TVector<NSearchMapParser::TShardsInterval> GetDonorInfo(const NSearchMapParser::TSearchMapHost& host) const;
        TVector<TIntervalLink> GetRestoreInfo(const NSearchMapParser::TSearchMapHost& host) const;

        TDonorsBuilder(const TVector<NSearchMapParser::TSearchMapHost>& restoreSlots, const TVector<NSearchMapParser::TSearchMapHost>& usefulSlots) {
            RestoreSlots = restoreSlots;
            UsefulSlots = usefulSlots;
            for (auto &i : RestoreSlots) {
                Intervals.push_back(TIntervalLink(i));
            }
        }

        bool BuildRemap();
    };
}
