/*
   Copyright (C) 1997-2001 Id Software, Inc.

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version 2
   of the License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

   See the GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

 */

#ifndef __TV_RELAY_H
#define __TV_RELAY_H

#include "tv_local.h"

#include "tv_client.h"

#define EDICT_NUM( u, n ) ( (edict_t *)( (qbyte *)u->edicts + u->edict_size*( n ) ) )
#define NUM_FOR_EDICT( u, e ) ( ( (qbyte *)( e )-(qbyte *)u->edicts ) / u->edict_size )

#define LOCAL_EDICT_NUM( u, n ) ( (edict_t *)( (qbyte *)u->local_edicts + u->local_edict_size*( n ) ) )
#define NUM_FOR_LOCAL_EDICT( u, e ) ( ( (qbyte *)( e )-(qbyte *)u->local_edicts ) / u->local_edict_size )

typedef struct packet_s packet_t;

struct packet_s
{
	unsigned int time;
	msg_t msg;
	packet_t *next;
};

#define RELAY_MIN_DELAY			3*1000		// 3 seconds

#ifdef WSW_RELEASE
#define RELAY_GLOBAL_DELAY		30*1000		// 30 seconds
#else
#define RELAY_GLOBAL_DELAY		RELAY_MIN_DELAY
#endif

#define MAX_FRAME_SOUNDS    256
#define MAX_TIME_DELTAS	    8

struct relay_s
{
	connstate_t state;

	upstream_t *upstream;

	tvm_relay_t *module;            // link to the module's relay struct
	tv_module_export_t *module_export;
	mempool_t *module_mempool;

	unsigned int lastrun;       // last RunFrame time
	int lastExecutedServerCommand;
	qboolean multiview;

	packet_t *packetqueue_pos;
	unsigned int delay;
	qboolean reliable;

	cmodel_state_t *cms;
	qbyte fatpvs[MAX_MAP_LEAFS/8];
	qbyte fatphs[MAX_MAP_LEAFS/8];

	struct edict_s *edicts;
	int edict_size;
	int num_edicts;
	int max_edicts;
	int max_clients;
	int num_active_clients;

	int numframesounds;
	sound_t	framesounds[MAX_FRAME_SOUNDS];      // global sounds for this frame

	struct edict_s *local_edicts;
	int local_edict_size;
	int local_num_edicts;
	int local_max_edicts;

	int serverTimeDeltas[MAX_TIME_DELTAS];
	int serverTimeDeltasHead;
	int serverTimeDelta;         // the time difference with the server time, or at least our best guess about it
	unsigned int serverTime;    // the best match we can guess about current time in the server
	unsigned int baseServerTime; // base where the server time starts to avoid cl.serverTime using to high values
	unsigned int snapFrameTime;

	// initial server state
	char configstrings[MAX_CONFIGSTRINGS][MAX_CONFIGSTRING_CHARS];
	entity_state_t baselines[MAX_EDICTS];

	// current server state
	frame_t	*lastFrame;             // latest snap received from the server
	frame_t	*lastUcmdFrame;         // latest snap sent in ucmd
	frame_t	*curFrame;              // latest snap handled
	frame_t	frames[UPDATE_BACKUP];
	unsigned int framenum;

	unsigned num_client_entities;           // maxclients->integer*UPDATE_BACKUP*MAX_PACKET_ENTITIES
	unsigned next_client_entities;          // next client_entity to use
	entity_state_t *client_entities;        // [num_client_entities]

	// serverdata
	int playernum;
	int servercount;
	char game[MAX_QPATH];
	char basegame[MAX_QPATH];
	char levelname[MAX_QPATH];
	unsigned map_checksum;
	int sv_bitflags;
	purelist_t *purelist;
};

void TV_Relay_Init( relay_t *relay, upstream_t *upstream, int delay );
void TV_Relay_ClearState( relay_t *relay );
void TV_Relay_InitMap( relay_t *relay );
void TV_Relay_Error( relay_t *relay, const char *format, ... );
void TV_Relay_Shutdown( relay_t *relay, const char *format, ... );
void TV_Relay_Run( relay_t *relay );
void TV_Relay_UpstreamUserinfoChanged( relay_t *relay );
void TV_Relay_NameNotify( relay_t *relay, client_t *client );

#endif // __TV_RELAY_H
