/*
   Copyright (C) 2007 Will Franklin

   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 _MASTER_H
#define _MASTER_H

#include "../qcommon/qcommon.h"
#include "../qcommon/sys_net.h"
#include "../../tools/db/db_public.h"
#include "mm_common.h"
#include "auth_public.h"

// mm ping tolerances
#define MATCH_PING_TIME 20000 // 20 seconds
#define SERVER_PING_TIME 20000 // 20 seconds
#define UNACKNOWLEDGED_PINGS 2

// client gameserver ping tolerances
#define MAX_PING 250
#define MAX_PING_DEVIATION 100

#define SKILL_LEVEL_TOLERANCE 5

#define Auth_Malloc( size ) Mem_Alloc( auth_mempool, size )
#define Auth_Free( data ) Mem_Free( data )

typedef struct
{
	char lastcmd[MAX_MM_CMD_LEN];
	unsigned long int senttime;
	void ( *callback )( void *server, const char *reply );
} mm_servercmd_t;

typedef struct mm_server_s
{
	char ip[32];
	char pass[10];
	mm_servercmd_t cmd;
	mm_match_t *match;

	unsigned long int lastping;
	unsigned long int lastack;
	int noack;

	int ping;

	struct mm_server_s *next;
} mm_server_t;

//================
// mm_main.c
//================
extern socket_t socket_loopback_client;
extern socket_t socket_loopback_server;
extern socket_t socket_udp;
extern socket_t socket_tcp;

extern mempool_t *mm_mempool;

extern cvar_t *mm_ip;
extern cvar_t *mm_port;

extern unsigned long int realtime;

void MM_Init( void );
void MM_Shutdown( void );
void MM_Frame( const int realmsec );
void MM_ReadPackets( void );
void MM_FakePacket( void );
void MM_ConnectionlessPacket( const socket_t *socket, const netadr_t *address, msg_t *msg );

//================
// mm_db.c
//================
#define DBTABLE_SERVERCMDS  "mm_servercmds"
#define DBTABLE_USERS       "punbb_users"
#define DBTABLE_USERSTATS   "mm_userstats"

extern MYSQL *db_handle;
extern cvar_t *db_host;
extern cvar_t *db_user;
extern cvar_t *db_pass;
extern cvar_t *db_name;

void        DB_Init( void );
void        DB_Shutdown( void );

db_status_t DB_Connect( MYSQL **handle, const char *host, const char *user, const char *pass, const char *db );
void        DB_Close( MYSQL **handle );

char *DB_Error( MYSQL *handle );

void        DB_EscapeString( /*MYSQL *handle,*/ char *out, const char *in, size_t size );
db_status_t DB_Query( MYSQL *handle, const char *format, ... );
db_status_t DB_FetchResult( MYSQL *handle, MYSQL_RES **res );
db_status_t DB_FetchRow( MYSQL_RES *res, MYSQL_ROW *row, const int rownum );
int         DB_NumRows( MYSQL_RES *res );
int         DB_AffectedRows( MYSQL *handle );
void        DB_FreeResult( MYSQL_RES **res );

//================
// mm_serverlist.c
//================
//void         MM_ForceServerList( void );
//void         MM_GetServerList( const qboolean force );
//void         MM_ParseServerList( const netadr_t *msaddr, msg_t *msg );
//void         MM_ParseServerInfo( const netadr_t *address, msg_t *msg );
extern mm_server_t *serverlist;

mm_server_t *MM_GetServerFromList( const char *ip );
void         MM_SendCmdToGameServer( mm_server_t *server, const char *cmd );
mm_server_t *MM_GetRandomServerFromList( mm_ignoreserver_t *ignores );
mm_server_t *MM_AddServerToList( const char *ip );
void         MM_DeleteServerFromList( const char *ip );
void         MM_ClearServer( mm_server_t *server );
void         MM_ServerList( void );
void         MM_CheckServerList( void );
mm_server_t *MM_GetSuitableServer( mm_match_t *match );


//================
// mm_oob.c
//================
void MMC_Acknowledge( const socket_t *socket, const netadr_t *address );
void MMC_AcknowledgePacket( const socket_t *socket, const netadr_t *address );
void MMC_Chat( const socket_t *socket, const netadr_t *address );
void MMC_Data( const socket_t *socket, const netadr_t *address );
void MMC_Drop( const socket_t *socket, const netadr_t *address );
void MMC_Heartbeat( const socket_t *socket, const netadr_t *address );
void MMC_Join( const socket_t *socket, const netadr_t *address );
void MMC_Ping( const socket_t *socket, const netadr_t *address );
void MMC_PingServer( const socket_t *socket, const netadr_t *address );
void MMC_Reply( const socket_t *socket, const netadr_t *address );

void MM_FindAndLockServer( mm_match_t *match );

//================
// mm_matches.c
//================
extern mm_matchlist_t *matchlist;

void     MM_SendMsgToClient( qboolean reliable, mm_client_t *client, const char *format, ... );
void     MM_SendMsgToClients( qboolean reliable, const mm_match_t *match, const char *format, ... );
qboolean MM_MatchesCriteria( mm_match_t *match, int gametype, mm_type_t skill_type, int skill_level, mm_type_t ping_type, int ping );
void     MM_MatchesList( void );
void     MM_PingClients( void );
int      MM_GetSkillLevelByStats( const int uid );
void     MM_ClearMatches( void );
#ifdef OLD_GAMESERVER_CHECKING 
void     MM_AddToIgnoreList( mm_match_t *match, const char *ip );
#endif
void     MM_CheckClientPackets( void );

//================
// auth_main.c
//================
extern mempool_t *auth_mempool;

void     Auth_Init( void );
void     Auth_Shutdown( void );
int      Auth_AuthenticateUser( const char *email, const char *pass );
qboolean Auth_CheckUserExistsById( const int uid );

//================
// auth_oob.c
//================
void AuthC_Auth( const socket_t *socket, const netadr_t *address );

#endif
