#pragma once

#include "sender_abstract.h"

#include <saas/library/socket_adapter/socket_adapter.h>

#include <util/network/socket.h>
#include <util/generic/ptr.h>

namespace NNeh {

    class TServiceStat;
    typedef TIntrusivePtr<TServiceStat> TServiceStatRef;
}

namespace NRTYServer {
    class TMessage;

    class TSocketContext: public NRTYServer::TInfoContext {
    public:
        using NRTYServer::TInfoContext::TInfoContext;
    };

    class TSlowOutputStream : public IOutputStream {
    public:
        TSlowOutputStream (IOutputStream& slave, const TDuration& duration)
            : Slave(slave), Duration(duration) {}
    protected:
        void DoWrite(const void* buf, size_t len) override {
            for (size_t i = 0; i < len; ++i) {
                Slave.Write((char*)buf + i, 1);
                Sleep(Duration);
            }
        }
    private:
        IOutputStream& Slave;
        const TDuration& Duration;
    };

    class TSocketSender: public NRTYServer::ISender {
    private:
        TString Host;
        ui16 Port;
        TDuration Timeout;
        mutable NNeh::TServiceStatRef Stat;
        TDuration InterByteTimeout;
        TString ProtocolType;
        TString AdapterToken;

        TAutoPtr<TSocket> Socket;
        TAutoPtr<TSocketInput> SocketInput;
        TAutoPtr<TSocketOutput> SocketOutputSlave;
        TAutoPtr<IOutputStream> SocketOutput;
        TAutoPtr<ISocketAdapter> Adapter;

    public:
        TSocketSender(const TString& host, const ui16 port, TDuration timeout, TDuration interByteTimeout, const TString& protocolType, const TString& service);
        ~TSocketSender() override;

        void Stop();

        NRTYServer::IContext::TPtr Send(const NRTYServer::TMessage& message, const TString& request) const override;

        NRTYServer::IContext::TPtr Send(const TString& message, const TString& request) const override;

        bool Recv(NRTYServer::IContext::TPtr /* context */, NRTYServer::TReply& reply, TDuration /*timeout*/) const override;

        bool Connect();
    };
};
