#pragma once

#ifdef NETWORK

#include "WebSocketClientBase.h"
#include <vector>
#include <atomic>
#include <memory>
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>

namespace ZL {

	// Lock-free SPSC double-buffer: producer pushes to one buffer, consumer swaps and drains the other.
	// No mutexes; avoids contention under high message load.
	class WebSocketClient : public WebSocketClientBase {
	private:
		boost::asio::io_context& ioc_;
		std::unique_ptr<boost::beast::websocket::stream<boost::beast::tcp_stream>> ws_;
		boost::beast::flat_buffer buffer_;

		// Incoming messages: I/O thread pushes, main thread drains in Poll()
		using MessageBuf = std::vector<std::string>;
		MessageBuf readBuffer0_;
		MessageBuf readBuffer1_;
		std::atomic<MessageBuf*> readProducerBuf_;
		std::atomic<MessageBuf*> readConsumerBuf_;

		// Outgoing messages: main thread pushes in Send(), doWrite()/completion drains
		using WriteBuf = std::vector<std::shared_ptr<std::string>>;
		WriteBuf writeBuffer0_;
		WriteBuf writeBuffer1_;
		std::atomic<WriteBuf*> writeProducerBuf_;
		std::atomic<WriteBuf*> writeConsumerBuf_;
		WriteBuf* currentWriteBuf_ = nullptr;
		size_t currentWriteIndex_ = 0;
		std::atomic<bool> isWriting_{ false };

		bool connected = false;


		void startAsyncRead();
		void processIncomingMessage(const std::string& msg);

	public:
		explicit WebSocketClient(boost::asio::io_context& ioc)
			: ioc_(ioc)
			, readProducerBuf_(&readBuffer0_)
			, readConsumerBuf_(&readBuffer1_)
			, writeProducerBuf_(&writeBuffer0_)
			, writeConsumerBuf_(&writeBuffer1_)
		{}

		void Connect(const std::string& host, uint16_t port) override;
		void Disconnect() override;

		void Poll() override;

		void Send(const std::string& message) override;
		void doWrite();

		bool IsConnected() const override { return connected; }
	};
}
#endif
