/* HoldingNuts network protocol specification as EBNF */


/* General structure of server and client messages */
Message = MessageBody  CRLF ;
MessageBody = MsgName  { S  MsgArg } ;
MsgName = ? uppercase-characters ? ;
MsgArg = ( TextSimple | TextQuoted ) ;
S = ' ' | '\t' ;	/* Space or Tab */
CRLF =  '\r' '\n' ;	/* CR LF */


/* Number definitions */
INT = ? signed-integer ?
UINT = ? unsigned-integer ?
FLOAT = ? single-precision-float ?

/* Text definitions */
TextSimple = ? character-sequence - ( S | '"' ) ? ;
TextQuoted = '"'  ? character-sequence - '"' ?  '"' ;

/* Misc definitions */
ClientId = UINT ;	/* unique client identifier */
GameId = UINT ;		/* unique game identifier */
TableId = UINT ;	/* unique table identifier for a specific game */


////////////////////////////////////////////////////////////////////////////////
//// Server messages
////////////////////////////////////////////////////////////////////////////////

/* Status response to a client request */

[ MessageId  S ]  ( 'OK' | 'ERR' )  [ S  StatusCode ]  [ S  StatusText ] ;

MessageId = UINT ;		/* id the client associated its message with */
StatusCode = UINT ;		/* error/success code */
StatusText = TextSimple ;	/* additional information */

================================================================================
/* Protocol introduction response */

'PSERVER'  S  ServerVersion  S  ClientId  S  Timestamp ;

ServerVersion = UINT ;	/* the server version */
ClientId = UINT ;	/* server-assigned-client-id */
Timestamp = UINT ;	/* server time as UNIX timestamp */

================================================================================
/* Chat message */

'MSG'  S  MsgFrom  S  MsgFromName  S  MsgText ;

MsgFrom = (
	'-1'					/* server */
	| ClientId				/* client at foyer */
	| GameId ':' ( '-1' | TableId )		/* game/table message */
	| GameId ':' TableId ':' ClientId	/* client at table */
) ;
MsgFromName = '???' | TextQuoted ;
MsgText = TextQuoted ;

================================================================================
/* Game list */

'GAMELIST'  { S  GameId } ;

================================================================================
/* Game info */

'GAMEINFO'  S  GameId  { S  GameInfoType ':' GameInfoValue } ;

GameInfoType =  ;
GameInfoValue = TextSimple ;

================================================================================
/* Player list */

'PLAYERLIST'  S  GameId  { S  ClientId } ;

================================================================================
/* Player info */

'CLIENTINFO'  S  ClientId  { S  ClientInfoType ':' ClientInfoValue } ;

ClientInfoType = <<FIXME>> ;
ClientInfoValue = TextSimple ;

================================================================================
/* Snapshots */

'SNAP'  S  SnapFrom  S  SnapType  { S  SnapInfoType ':' SnapInfoValue } ;

SnapFrom = GameId ':' TableId  |  GameId ':' '-1' ;
SnapType = SnapGameState | SnapTable | SnapHoleCards | <<FIXME>>;
SnapInfoType = ? depends-on-SnapType ?
SnapInfoValue = ? depends-on-SnapInfoType ?



////////////////////////////////////////////////////////////////////////////////
//// Client messages
////////////////////////////////////////////////////////////////////////////////

/* Protocol introduction request */

'PCLIENT'  S  ClientVersion  [ S  ClientUUID ] ;

ClientVersion = UINT ;		/* the server version */
ClientUUID = TextSimple ;	/* unique client identifier */

================================================================================
/* Client info */

'INFO'  { S  InfoType ':' InfoValue } ;

InfoType = <<FIXME>> ;
InfoValue = TextSimple ;


================================================================================
/* Chat message */

'CHAT'  S  MsgTo  S  MsgText ;

MsgFrom = (
	'-1'				/* to foyer */
	| ClientId			/* to specific client */
	| GameId ':' TableId		/* to table */
) ;
MsgText = TextQuoted ;


================================================================================
/* Requests */

'REQUEST'  S  RequestType  [ S  RequestValue ] ;

RequestType = <<FIXME>> ;
RequestValue = ? depends-on-RequestType ? ;


================================================================================
/* Register */

'REGISTER'  S  GameId  [ S  Password ] ;

Password = TextSimple ;


================================================================================
/* Unregister */

'UNREGISTER'  S  GameId ;


================================================================================
/* Table action */

'ACTION'  S  GameId  S  ActionType  [ S  Amount ] ;

ActionType = <<FIXME>> ;
Amount = UINT ;


================================================================================
/* Create a game */

'CREATE'  S  GameId  { S  CreateType ':' CreateValue } ;

CreateType = <<FIXME>> ;
CreateValue = ? depends-on-CreateType ?


================================================================================
/* Authenticate */

'AUTH'  S  AuthType  S  Password ;

AuthType = ( -1 | GameId ) ;		/* -1 = server auth */
Password = TextSimple ;


================================================================================
/* Quit request */

'QUIT'  [ S  QuitCode  [ S  QuitReason ]] ;

QuitCode = INT ;
QuitReason = TextSimple ;
