#include "headers.h"

#include "http.h"

#include <balancer/kernel/helpers/cast.h>
#include <balancer/kernel/helpers/default_instance.h>
#include <balancer/kernel/regexp/regexp_pire.h>

using namespace NSrvKernel;

namespace {
    struct THeadersToCheck: public TFsm , public TWithDefaultInstance<THeadersToCheck> {
        THeadersToCheck() noexcept
            : TFsm(
                  TFsm("Connection", TFsm::TOptions().SetCaseInsensitive(true))
                | TFsm("Keep-Alive", TFsm::TOptions().SetCaseInsensitive(true))
                | TFsm("Content-Length", TFsm::TOptions().SetCaseInsensitive(true))
                | TFsm("Transfer-Encoding", TFsm::TOptions().SetCaseInsensitive(true))
                | TFsm("Server", TFsm::TOptions().SetCaseInsensitive(true)))
            , ConnectionMatcher(TFsm(".*Keep-Alive.*", TFsm::TOptions().SetCaseInsensitive(true)) | TFsm(".*Close.*", TFsm::TOptions().SetCaseInsensitive(true)))
        {}

        const TFsm ConnectionMatcher;
    };
}

void TBaseProperties::SetReasonableDefaults(TResponse* r) noexcept {
    if (r->ResponseLine().MajorVersion == 1 && r->ResponseLine().MinorVersion == 1) {
        if (!r->Props().ExplicitConnectionHeader) {
            KeepAlive = 1;
        }
        Version = 1;
    } else {
        if (!r->Props().ExplicitConnectionHeader) {
            KeepAlive = 0;
        }
        Version = 0;
    }
}

void TBaseProperties::SetReasonableDefaults(TRequest* r) noexcept {
    if (r->RequestLine().MajorVersion == 1 && r->RequestLine().MinorVersion == 1) {
        if (!r->Props().ExplicitConnectionHeader) {
            KeepAlive = 1;
        }
        Version = 1;
    } else {
        if (!r->Props().ExplicitConnectionHeader) {
            KeepAlive = 0;
        }
        Version = 0;
    }
}

void TBaseProperties::BuildTo(IOutputStream& out) const noexcept {
    out << "Version" << HDRD << Version << CRLF;
    if (ContentLength.has_value()) {
        out << "Content-Length" << HDRD << *ContentLength << CRLF;
    }
    out << "KeepAlive" << HDRD << KeepAlive << CRLF;
    out << "ExplicitKeepAliveHeader" << HDRD << ExplicitKeepAliveHeader << CRLF;
    out << "ExplicitConnectionHeader" << HDRD << ExplicitConnectionHeader << CRLF;
    out << "ChunkedTransfer" << HDRD << ChunkedTransfer << CRLF;
    out << "TransferedWholeRequest" << HDRD << TransferedWholeRequest << CRLF;
    out << "UpgradeRequested" << HDRD << UpgradeRequested << CRLF;
    out << "Reused" << HDRD << Reused << CRLF;
}

void NSrvKernel::RemoveHeaders(THeaders* hdrs) noexcept {
    hdrs->Delete(THeadersToCheck::Instance());
}

void NSrvKernel::InitHeadersParser() noexcept {
    THeadersToCheck::Instance();
}
