#include "saas_api.h"
#include <library/cpp/logger/global/global.h>

namespace NCommonProxy {

    class TSaasApiSender::TMustBeSetFieldFilter final : public TLink::IFilter{
    public:
        TMustBeSetFieldFilter(const TSaasApiSender::TConfig& config)
            : Config(config)
        {}

        virtual bool Accepted(const TDataSet::TPtr input) const override {
            if (!input->IsSet(Config.DocFieldName)) {
                return false;
            }
            switch (Config.PrefixFilter) {
            case TSaasApiSender::TConfig::EPrefixFilterStyle::All:
                return true;
            case TSaasApiSender::TConfig::EPrefixFilterStyle::PrefixedOnly:
                return (*input->GetObject<TSaasAction>(Config.DocFieldName))->GetPrefix() != 0;
            case TSaasApiSender::TConfig::EPrefixFilterStyle::NotPrefixedOnly:
                return (*input->GetObject<TSaasAction>(Config.DocFieldName))->GetPrefix() == 0;
            }
        }

    private:
        const TSaasApiSender::TConfig& Config;
    };

    TSaasApiSender::TSaasApiSender(const TString& name, const TProcessorsConfigs& configs)
        : TSender(name, configs)
        , Config(*configs.Get<TConfig>(name))
        , InputMeta(Config.DocFieldName)
        , Sender(ISaasSendingClient::Create(name, Config.Sender, Config.PQSender, Config.CheckMessage))
    {
    }

    void TSaasApiSender::DoStart() {
        Sender->Start();
    }

    void TSaasApiSender::DoStop() {
        Sender->Stop();
    }

    void TSaasApiSender::DoWait() {
        Sender->Wait();
    }

    const NCommonProxy::TMetaData& TSaasApiSender::GetInputMetaData() const {
        return InputMeta;
    }

    const NCommonProxy::TMetaData& TSaasApiSender::GetOutputMetaData() const {
        return TMetaData::Empty;
    }

    void TSaasApiSender::DoProcess(TDataSet::TPtr input, IReplier::TPtr replier) const {
        TIntrusivePtr<TSaasAction> action = input->GetObject<TSaasAction>(Config.DocFieldName);
        if (action) {
            Sender->Send(**action, replier);
        }
    }

    void TSaasApiSender::CollectInfo(NJson::TJsonValue& result) const {
        TSender::CollectInfo(result);
        result["in_fly"] = Sender->GetInFly();
    }

    void TSaasApiSender::UpdateUnistatSignals() const {
        TSender::UpdateUnistatSignals();
        Sender->UpdateUnistatSignals();
    }

    void TSaasApiSender::DoRegisterSignals(TUnistat& tass) const {
        TSender::DoRegisterSignals(tass);
        Sender->RegisterSignals(tass);
    }

    void TSaasApiSender::AddRequester(TLink::TPtr link) {
        link->SetFilter<TMustBeSetFieldFilter>(Config);
    }

    bool TSaasApiSender::TConfig::DoCheck() const {
        return true;
    }

    void TSaasApiSender::TConfig::DoInit(const TYandexConfig::Section& section) {
        TProcessorConfig::DoInit(section);
        const auto& dir = section.GetDirectives();
        DocFieldName = dir.Value("DocFieldName", TSaasActionMeta::FieldName);
        dir.GetValue("PrefixFilter", PrefixFilter);
        Sender.Init(section);
        const auto children = section.GetAllChildren();
        auto pqSender = children.find("PQ");
        if (pqSender != children.cend()) {
            PQSender.Init(*pqSender->second);
        }
        auto checkMessage = children.find("CheckMessage");
        if (checkMessage != children.cend()) {
            CheckMessage.Init(*checkMessage->second);
        } else {
            CheckMessage.SetDisabled(true);
        }
    }

    void TSaasApiSender::TConfig::DoToString(IOutputStream& so) const {
        TProcessorConfig::DoToString(so);
        so << "DocFieldName: " << DocFieldName << Endl;
        so << "PrefixFilter: " << PrefixFilter << Endl;
        Sender.ToString(so);
        so << "<PQ>" << Endl;
        PQSender.ToString(so);
        so << "</PQ>" << Endl;
        so << "<CheckMessage>" << Endl;
        CheckMessage.ToString(so);
        so << "</CheckMessage>" << Endl;
    }
}
