#include "http2_edge_prio_fix.h"

#include <balancer/kernel/http2/server/common/http2_headers_fsm.h>

#include <balancer/kernel/memory/chunks.h>

namespace NSrvKernel::NHTTP2 {

    TEdgePrioFix::TEdgePrioFix(const TAuxServerSettings& auxServerSettings) noexcept
        : Settings_(auxServerSettings)
    {}

    void TEdgePrioFix::OnPriority(const TPriority& prio) noexcept {
        if (IsEnabled() && TPriority::EOrigin::None != prio.Origin) {
            MaybeEdge_ = false;
        }
    }

    TMaybe<TPriority> TEdgePrioFix::OnResponse(const THeaders& respHeaders) noexcept {
        if (!IsEnabled()) {
            return Nothing();
        }

        bool highPrioContentType = false;
        TMaybe<ui32> highPrioWeight;

        for (const auto& header : respHeaders) {
            if (IsContentType(header.first.AsStringBuf())) {
                highPrioContentType = IsValueHighPrioContentType(header.second.back().AsStringBuf());
            } else if (IsXYandexH2PrioEdge(header.first.AsStringBuf())) {
                highPrioWeight = 0;
                TryFromString(header.second.back().AsStringBuf(), *highPrioWeight);
            }
        }

        TPriority res;
        res.Origin = TPriority::EOrigin::EdgePrioFix;
        res.RawWeight = (RFC_PRIO_WEIGHT_MAX / 2) - 1;

        if (highPrioWeight && *highPrioWeight) {
            res.RawWeight = Min<ui32>(RFC_PRIO_RAW_WEIGHT_MAX, *highPrioWeight - 1);
        }

        if (highPrioContentType || highPrioWeight && *highPrioWeight) {
            return res;
        } else {
            return Nothing();
        }
    }

    bool TEdgePrioFix::IsEnabled() const noexcept {
        return MaybeEdge_ && Settings_.EdgePrioFixEnabled;
    }

}
