#pragma once

#include <balancer/kernel/io/iobase.h>
#include <balancer/kernel/memory/chunks.h>
#include <balancer/kernel/memory/split.h>

#include <utility>

namespace NSrvKernel {
    class TChunksOutput final : public IIoOutput {
    public:
        const TChunkList& Chunks() const & noexcept {
            return Data_;
        }

        TChunkList& Chunks() & noexcept {
            return Data_;
        }

        TChunkList&& Chunks() && noexcept {
            return std::move(Data_);
        }

    private:
        TError DoSend(TChunkList lst, TInstant) noexcept override {
            lst.MakeOwned();
            Data_.Append(std::move(lst));
            return {};
        }

    private:
        TChunkList Data_;
    };

    class TChunksInput : public IIoInput {
    public:
        TChunksInput(TChunkList&& chunks) noexcept
            : Data_(std::move(chunks))
        {}

    private:
        TError DoRecv(TChunkList& lst, TInstant) noexcept override {
            lst.Append(std::move(Data_));
            return {};
        }

    private:
        TChunkList Data_;
    };

    class TChunksIo final : public IIoInput, public IIoOutput {
    public:
        TChunksIo() noexcept = default;

        const TChunkList& Chunks() const & noexcept {
            return Data_;
        }

        TChunkList& Chunks() & noexcept {
            return Data_;
        }

        TChunkList&& Chunks() && noexcept {
            return std::move(Data_);
        }

    private:
        TError DoSend(TChunkList lst, TInstant) noexcept override {
            Data_.Append(std::move(lst));
            return {};
        }

        TError DoRecv(TChunkList& lst, TInstant) noexcept override {
            lst.Append(std::move(Data_));
            return {};
        }

    private:
        TChunkList Data_;
    };
}
