#pragma once

#ifdef NETWORK

#include "NetworkInterface.h"
#include <queue>
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>

namespace ZL {

	class WebSocketClient : public INetworkClient {
	private:
		// Переиспользуем io_context из TaskManager
		boost::asio::io_context& ioc_;

		// Объекты переехали в члены класса
		std::unique_ptr<boost::beast::websocket::stream<boost::beast::tcp_stream>> ws_;
		boost::beast::flat_buffer buffer_;

		std::queue<std::string> messageQueue;
		std::mutex queueMutex; // Защита для messageQueue

		std::queue<std::shared_ptr<std::string>> writeQueue_;
		bool isWriting_ = false;
		std::mutex writeMutex_; // Отдельный мьютекс для очереди записи

		bool connected = false;
		int clientId = -1;

		std::unordered_map<int, ClientStateInterval> remotePlayers;
		std::mutex playersMutex;

		// Серверные коробки
		std::vector<std::pair<Eigen::Vector3f, Eigen::Matrix3f>> serverBoxes_;
		std::mutex boxesMutex;

		std::vector<ProjectileInfo> pendingProjectiles_;
		std::mutex projMutex_;

		std::vector<DeathInfo> pendingDeaths_;
		std::mutex deathsMutex_;

		std::vector<int> pendingRespawns_;
		std::mutex respawnMutex_;

		std::vector<BoxDestroyedInfo> pendingBoxDestructions_;
		std::mutex boxDestructionsMutex_;

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

	public:
		explicit WebSocketClient(boost::asio::io_context& ioc) : ioc_(ioc) {}

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

		void Poll() override;

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

		bool IsConnected() const override { return connected; }
		int GetClientId() const override { return clientId; }

		std::unordered_map<int, ClientStateInterval> getRemotePlayers() override {
			std::lock_guard<std::mutex> lock(playersMutex);
			return remotePlayers;
		}

		std::vector<std::pair<Eigen::Vector3f, Eigen::Matrix3f>> getServerBoxes() override {
			std::lock_guard<std::mutex> lock(boxesMutex);
			return serverBoxes_;
		}

		std::vector<ProjectileInfo> getPendingProjectiles() override;
		std::vector<DeathInfo> getPendingDeaths() override;
		std::vector<int> getPendingRespawns() override;
		std::vector<BoxDestroyedInfo> getPendingBoxDestructions() override;
	};
}
#endif
