#pragma once

#include "docstream.h"
#include <saas/rtyserver/docfetcher/config_wd.h>

namespace NJson {
    class TJsonValue;
}

class TWatchdogOptionsCollection;

namespace NFusion {
    struct TStreamConfig;
    struct TMinRankCondition;

    class TDistributorStream : public TDocStream, SignalsHolder<> {
        using TBase = TDocStream;

    public:
        class IIterator {
        public:
            virtual ~IIterator() {
            }
            virtual NFusion::TActionPtr GetDoc() = 0;
            virtual NJson::TJsonValue GetStatus() const = 0;
            virtual bool IsExhausted() const = 0;
            virtual void SetActive(bool value) = 0;
            virtual void SetAge(ui32 value) = 0;
            virtual void SetMinRank(const TMinRankCondition& cond) = 0;
        };

    protected:
        struct TMetrics: public TCompositeMetric {
            TPart<TOrangeMetric> DistAge;
            TPart<TOrangeMetric> AckAge;
            TPart<TOrangeMetric> DistributorTimestamp;
            TPart<TOrangeMetric> IndexedDocTimestamp;

            TMetrics(const TString& name)
                : DistAge(this, GetMetricsPrefix() + JoinMetricName("DistAge", name))
                , AckAge(this, GetMetricsPrefix() + JoinMetricName("AckAge", name))
                , DistributorTimestamp(this, GetMetricsPrefix() + JoinMetricName("DistributorTimestamp", name))
                , IndexedDocTimestamp(this, GetMetricsPrefix() + JoinMetricName("IndexedDocTimestamp", name))
            {
            }
        };

    public:
        TDistributorStream(const TDocFetcherModule& owner, const TStreamConfig& config, const TRTYServerConfig& globalConfig, TLog& log);
        ~TDistributorStream();

        void OnWatchdogOption(const TString& key, const TString& value) override;
        void SubscribeToWatchdog(IWatchdogOptions& w) override;

    protected: // TDocStream
        virtual void OnDocStreamStart() override;
        virtual void OnDocStreamStop() override;
        virtual void OnReply(const NRTYServer::TReply& reply, NFusion::TActionPtr action) override;
        virtual bool IsExhausted() const override;
        virtual void OnExhausted(TTimeToSleep& timeToSleep) override;
        virtual TDuration GetDelay() const override;
        virtual NFusion::TActionPtr GetDoc(TMap<TString, TString>& propsToLog, bool& /*skipSleepOnError*/) override;
        virtual void ReportStatus(NJson::TJsonValue& status) override;

        TCommonDocStreamSignals* SignalsBase() const override {
            return SignalsHolder<>::Signals();
        }

    protected: // IMessageProcessor
        virtual bool Process(IMessage* message) override;

    protected:
        void SetTimestamp(TInstant ts, bool incrementOnly);

    private:
        TDuration GetDelay(const NRTYServer::TTimestampSnapshot& snapshot) const;
        TDuration GetDelayConsistent(const NRTYServer::TTimestampSnapshot& snapshot) const;
        TDuration GetDelayLegacy(const NRTYServer::TTimestampSnapshot& snapshot) const;

    private:
        const TStreamConfig& Config;
        TAutoGlobal<TMetrics> Metrics;
        TDocfetcherItsOptions ItsOptions;

        THolder<IIterator> Iterator;

        TWatchdogSubscription Watchdog;
    };
}
