#pragma once

#include <balancer/kernel/memory/chunks.h>
#include <balancer/kernel/process/initializer.pb.h>
#include <library/cpp/coroutine/engine/impl.h>
#include <balancer/kernel/process_common/two_nonblocking_pipe.h>
#include <util/network/poller.h>
#include <util/stream/output.h>
#include <util/system/pipe.h>

#include <utility>

namespace NSrvKernel {
    enum class EIoResult {
        COMPLETED,
        PARTIALLY_COMPLETED,
        EOF_OCCURED
    };

    class TTwoNonblockingPipes;
    using TTwoNonblockingPipesPtr = THolder<TTwoNonblockingPipes>;
    class TMasterStream;
    using TMasterStreamPtr = THolder<TMasterStream>;

    class TMasterStream {
    public:
        TMasterStream()
            : Input_()
            , InputBuffer_(1024)
            , Remaining_(-1)
            , OutputBuffer_(1024)
            , Filled_(0)
        {
        }
        PIPEHANDLE GetOutputHandle() const {
            return Output_.GetHandle();
        }
        void* GetOutputCookie() {
            return &Output_;
        }

        PIPEHANDLE GetInputHandle() const {
            return Input_.GetHandle();
        }
        void* GetInputCookie() {
            return &Input_;
        }

        void EnqueueWrite(const TInitializerMessage& message);
        EIoResult Write();
        EIoResult Read(TInitializerMessage* message);

    private:
        TPipe Input_;
        TBuffer InputBuffer_;
        i32 Remaining_;

        TPipe Output_;
        TBuffer OutputBuffer_;
        ui32 Filled_;

        friend std::pair<TMasterStreamPtr, TTwoNonblockingPipesPtr> SetupMasterPipes();
    };

    std::pair<TMasterStreamPtr, TTwoNonblockingPipesPtr> SetupMasterPipes();
}
