#pragma once

#include "client_proto.h"

#include <util/system/defaults.h>
#include <balancer/kernel/helpers/errors.h>

#include <optional>

namespace NSrvKernel {
    class THeaders;
    class TRequest;
    class TResponse;
    //TODO - inherit from common ancestor

    struct THTTP2StreamDetails {
        enum class EFinalState : ui32 {
            Unknown = 0,
            Closed,
            ResetByClient,
            ResetByServer,
            ConnError,
            ConnCancel,
            ConnClose,
            Count
        };

        EFinalState FinalState = EFinalState::Unknown;
        THTTP2Error::EErrorCode ErrorCode = THTTP2Error::EErrorCode::NO_ERROR;

        [[nodiscard]] bool IsReset() const noexcept {
            return IsIn({EFinalState::ResetByClient, EFinalState::ResetByServer, EFinalState::ConnError},
                FinalState
            );
        }

        [[nodiscard]] bool IsConnCancel() const noexcept {
            return EFinalState::ConnCancel == FinalState;
        }

        [[nodiscard]] bool IsCancelledByClient() const noexcept {
            return EFinalState::ResetByClient == FinalState && THTTP2Error::EErrorCode::CANCEL == ErrorCode;
        }

        [[nodiscard]] bool IsClosedByClient() const noexcept {
            return IsIn({EFinalState::ResetByClient, EFinalState::ConnError, EFinalState::ConnClose},
                FinalState
            );
        }
    };


    struct TBaseProperties {
        THTTP2StreamDetails* HTTP2 = nullptr;
        ui16 Version = 1; // It actually duplicates the version in TRequestLine or TResponseLine
        std::optional<ui64> ContentLength;
        bool KeepAlive = true;
        bool ExplicitKeepAliveHeader = false; // for Keep-Alive or Close
        bool ExplicitConnectionHeader = false;
        bool ChunkedTransfer = false;
        bool TransferedWholeRequest = false;
        bool UpgradeRequested = false;
        bool Reused = false;
        bool AddExplicitConnectionHeader = false;
        std::optional<EClientProto> ClientProto;

        TBaseProperties() noexcept = default;

        void SetReasonableDefaults(TRequest* req) noexcept;
        void SetReasonableDefaults(TResponse* resp) noexcept;

        void BuildTo(IOutputStream& out) const noexcept;
    };

    void RemoveHeaders(THeaders* hdrs) noexcept;
    void InitHeadersParser() noexcept;
}
