#pragma once

#include <brynet/net/http/HttpService.hpp>
#include <brynet/net/wrapper/ServiceBuilder.hpp>
#include <utility>

class HttpListenerBuilder {
public:
	HttpListenerBuilder &WithService(TcpService::Ptr service) {
		mBuilder.WithService(std::move(service));
		return *this;
	}

	HttpListenerBuilder &WithEnterCallback(HttpSession::EnterCallback &&callback) {
		mHttpEnterCallback = std::move(callback);
		return *this;
	}

	HttpListenerBuilder &AddSocketProcess(const ListenThread::TcpSocketProcessCallback &callback) {
		mBuilder.AddSocketProcess(callback);
		return *this;
	}

	HttpListenerBuilder &WithMaxRecvBufferSize(size_t size) {
		mBuilder.WithMaxRecvBufferSize(size);
		return *this;
	}
#ifdef BRYNET_USE_OPENSSL
	HttpListenerBuilder &WithSSL(SSLHelper::Ptr sslHelper) {
		mBuilder.WithSSL(std::move(sslHelper));
		return *this;
	}
#endif
	HttpListenerBuilder &WithForceSameThreadLoop() {
		mBuilder.WithForceSameThreadLoop();
		return *this;
	}

	HttpListenerBuilder &WithAddr(bool ipV6, std::string ip, size_t port) {
		mBuilder.WithAddr(ipV6, std::move(ip), port);
		return *this;
	}

	HttpListenerBuilder &WithReusePort() {
		mBuilder.WithReusePort();
		return *this;
	}

	void asyncRun() {
		if (mHttpEnterCallback == nullptr) {
			throw BrynetCommonException("not setting http enter callback");
		}

		auto callback = mHttpEnterCallback;
		mBuilder.AddEnterCallback([callback](const TcpConnection::Ptr &session) {
			HttpService::setup(session, callback);
		});
		mBuilder.asyncRun();
	}

private:
	HttpSession::EnterCallback mHttpEnterCallback;
	ListenerBuilder mBuilder;
};
