#pragma once

#include "NetworkInterface.h"
#include <vector>
#include <unordered_map>

namespace ZL {

	// All state in WebSocketClientBase is only accessed from the main thread:
	// HandlePollMessage() runs from Poll(), and get*() are called from Game/Space on the main thread.
	// No mutexes needed.
	class WebSocketClientBase : public INetworkClient {
	protected:
		std::unordered_map<int, ClientStateInterval> remotePlayers;

		std::vector<std::pair<Eigen::Vector3f, Eigen::Matrix3f>> serverBoxes_;
		std::vector<bool> serverBoxesDestroyed_;

		std::vector<ProjectileInfo> pendingProjectiles_;
		std::vector<DeathInfo> pendingDeaths_;
		std::vector<int> pendingRespawns_;
		std::vector<BoxDestroyedInfo> pendingBoxDestructions_;
		std::vector<BoxPickedUpInfo> pendingBoxPickups_;
		std::vector<BoxRespawnInfo> pendingBoxRespawns_;
		std::vector<int> pendingDisconnects_;
		int clientId = -1;
		int64_t timeOffset = 0;
		std::vector<ClientState> pendingSpawns_;

	public:
		int GetClientId() const override { return clientId; }

		int64_t getTimeOffset() const override { return timeOffset; }

		void HandlePollMessage(const std::string& msg);

		std::string SignMessage(const std::string& msg);

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

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

		std::vector<bool> getServerBoxDestroyedFlags() override {
			return serverBoxesDestroyed_;
		}

		std::vector<ProjectileInfo> getPendingProjectiles() override;
		std::vector<DeathInfo> getPendingDeaths() override;
		std::vector<int> getPendingRespawns() override;
		std::vector<BoxDestroyedInfo> getPendingBoxDestructions() override;
		std::vector<BoxPickedUpInfo> getPendingBoxPickups() override;
		std::vector<BoxRespawnInfo> getPendingBoxRespawns() override;
		std::vector<int> getPendingDisconnects() override;
		std::vector<ClientState> getPendingSpawns();
		int getClientId() const { return clientId; }
	};

}

