// wj_input.h -- shared state between the civetweb server threads (wj_server.cpp)
// and the main game thread (wj_ticcmd.cpp). This is the ONLY data that may be
// touched from a civetweb worker thread; everything else (playeringame[],
// players[], netcmds[]) is main-thread-only and is updated by WJ_Tick(),
// which drains the structures defined here once per gametic.
#pragma once

#include <mutex>
#include <string>
#include <vector>
#include <cstdint>
#include "doomdef.h"

// Wire format sent by the phone's WebSocket client, 12 bytes, little-endian.
// Kept deliberately tiny since it's sent at ~35 Hz per connected phone.
struct WJInputPacket
{
	uint32_t buttons;	// subset of buttoncode_t (BT_ATTACK, BT_USE, BT_JUMP, ...)
	int16_t  moveX;		// strafe stick, -32768..32767 for -1..1
	int16_t  moveY;		// forward/back stick, -32768..32767 for -1..1
	int16_t  turnX;		// look left/right stick, -32768..32767 for -1..1
	int16_t  turnY;		// look up/down stick, -32768..32767 for -1..1
};

// Latest known input state for one connected phone. There is one of these
// per player slot (index-matched to players[]/playeringame[]). Written by
// a civetweb worker thread on each WS message; read once per gametic by
// WJ_Tick() on the main thread.
struct WJRemoteInput
{
	std::mutex mtx;
	bool connected = false;
	WJInputPacket packet = {};
};

extern WJRemoteInput wj_remoteInput[MAXPLAYERS];

// A phone that has completed the WebSocket handshake but has not yet been
// admitted to a player slot on the main thread. civetweb's WS-ready callback
// (running on its own worker thread) only ever pushes into this queue --
// it never touches playeringame[]/players[] itself. WJ_Tick() drains it.
struct WJPendingJoin
{
	int connToken;		// opaque id assigned by wj_server, used to route WJ_OnSlotAssigned back to the right mg_connection
	std::string name;
};

// Thread-safe queue of connections waiting for a player slot. Pushed to by
// wj_server.cpp (civetweb threads), drained by wj_ticcmd.cpp (main thread).
struct WJJoinQueue
{
	std::mutex mtx;
	std::vector<WJPendingJoin> pending;
};
extern WJJoinQueue wj_joinQueue;

// Called by WJ_Tick() (main thread) once a pending connection has been
// admitted to player slot `slot`, so wj_server.cpp can associate future
// WS messages carrying connToken with wj_remoteInput[slot]. Implemented in
// wj_server.cpp. Returns false if connToken is no longer valid (phone
// disconnected before admission finished) -- WJ_Tick() must then undo the
// admission it just made, since nothing will ever feed that slot input.
bool WJ_OnSlotAssigned(int connToken, int slot);
