#include "http2_flow.h"

namespace NSrvKernel::NHTTP2 {

    TFlowBase::TFlowBase(TLogger& logger) noexcept
        : Logger_(logger)
    {}

    TError TFlowBase::Consume(ui32 consumeSize) noexcept {
        Y_HTTP2_FUNC(Logger_, GetCurrentSize(), consumeSize);

        if (GetCurrentSize() < consumeSize) {
            return ThrowOnConsumeUnderflow(GetCurrentSize(), consumeSize);
        }

        WindowDelta_ -= consumeSize;
        OnConsume();
        return {};
    }

    TError TFlowBase::Update(ui32 updateSize) noexcept {
        Y_HTTP2_FUNC(Logger_, GetCurrentSize(), updateSize);

        if (!updateSize) {
            return ThrowOnZeroUpdate();
        }

        Y_PROPAGATE_ERROR(DoValidateUpdate(updateSize));

        WindowDelta_ += updateSize;
        return OnUpdate();
    }

    ui32 TFlowBase::GetAvailableSize() const noexcept {
        return (ui32)std::max<i64>(0, GetCurrentSize());
    }

    i64 TFlowBase::GetCurrentSize() const noexcept {
        return WindowDelta_ + GetInitialSize();
    }

    TError TFlowBase::DoValidateUpdate(ui32 updateSize) const noexcept {
        Y_HTTP2_FUNC_E(Logger_);
        if (GetCurrentSize() + updateSize > (i64)RFC_WINDOW_SIZE_MAX) {
            return ThrowOnUpdateOverflow(GetCurrentSize(), updateSize);
        }
        return {};
    }

    TError TFlowBase::UpdateInitialSize() noexcept {
        Y_HTTP2_FUNC_E(Logger_);
        Y_PROPAGATE_ERROR(DoValidateUpdate(0));
        return OnUpdate();
    }
}

Y_HTTP2_GEN_PRINT(TStreamRecvFlow);
Y_HTTP2_GEN_PRINT(TConnRecvFlow);
Y_HTTP2_GEN_PRINT(TStreamSendFlow);
Y_HTTP2_GEN_PRINT(TConnSendFlow);
