#include <math.h>
#include <stdlib.h>
#include <string.h>

#define CVAR_IMPLEMENTOR 1

#include "doomtype.h"
#include "doomdef.h"
#include "doomstat.h"
#include "d_netinf.h"
#include "d_net.h"
#include "d_protocol.h"
#include "v_palette.h"
#include "v_video.h"
#include "i_system.h"
#include "r_draw.h"
#include "r_state.h"
#include "st_stuff.h"
#include "cl_main.h"

extern BOOL st_firsttime;

CVAR (autoaim,				"5000",		CVAR_USERINFO | CVAR_ARCHIVE)
CVAR (name,					"Player",	CVAR_USERINFO | CVAR_ARCHIVE)
CVAR (color,				"40 cf 00",	CVAR_USERINFO | CVAR_ARCHIVE)
CVAR (skin,					"base",		CVAR_USERINFO | CVAR_ARCHIVE)
CVAR (team,					"",			CVAR_USERINFO | CVAR_ARCHIVE)
CVAR (gender,				"male",		CVAR_USERINFO | CVAR_ARCHIVE)
CVAR (neverswitchonpickup,	"0",		CVAR_USERINFO | CVAR_ARCHIVE)


enum
{
	INFO_Name,
	INFO_Autoaim,
	INFO_Color,
	INFO_Skin,
	INFO_Team,
	INFO_Gender,
	INFO_NeverSwitchOnPickup
};

static const char *UserInfoStrings[] =
{
	"name",
	"autoaim",
	"color",
	"skin",
	"team",
	"gender",
	"neverswitchonpickup",
	NULL
};

int D_GenderToInt (const char *gender)
{
	if (!stricmp (gender, "female"))
		return GENDER_FEMALE;
	else if (!stricmp (gender, "cyborg"))
		return GENDER_NEUTER;
	else
		return GENDER_MALE;
}

void D_SetupUserInfo (void)
{
	userinfo_t *coninfo = &players[consoleplayer].userinfo;

    memset (&players[consoleplayer].userinfo, 0, sizeof(userinfo_t));

	strncpy (coninfo->netname, name.string, MAXPLAYERNAME);
	strncpy (coninfo->team, team.string, MAXPLAYERNAME);
	coninfo->aimdist = (fixed_t)(autoaim.value * 16384.0);
	coninfo->color = V_GetColorFromString (NULL, color.string);
	coninfo->skin = R_FindSkin (skin.string);
	coninfo->gender = D_GenderToInt (gender.string);
	coninfo->neverswitch = neverswitchonpickup.value ? true : false;
	R_BuildPlayerTranslation (consoleplayer, coninfo->color);
}

void D_UserInfoChanged (cvar_t *cvar)
{
	if (cvar == &autoaim)
	{
		if (cvar->value < 0.0f)
		{
			cvar->Set (0.0f);
			return;
		}
		else if (cvar->value > 5000.0f)
		{
			cvar->Set (5000.0f);
			return;
		}
	}

	if (gamestate != GS_STARTUP)
		D_SetupUserInfo();

	if (clact == ca_active)
		CL_SendUserInfo();
}


BOOL SetServerVar (char *name, char *value)
{
	cvar_t *dummy;
	cvar_t *var = FindCVar (name, &dummy);

	if (var)
	{
		unsigned oldflags = var->flags;

		var->flags &= ~(CVAR_SERVERINFO|CVAR_LATCH);
		var->Set (value);
		var->flags = oldflags;
		return true;
	}

	return false;
}


void D_SendServerInfoChange (const cvar_t *cvar, const char *value)
{
	SetServerVar (cvar->name, (char *)value);
}

void D_DoServerInfoChange (byte **stream)
{
}

void D_WriteUserInfoStrings (int i, byte **stream, bool compact)
{
}

void D_ReadUserInfoStrings (int i, byte **stream, bool update)
{
}

FArchive &operator<< (FArchive &arc, userinfo_t &info)
{
	arc.Write (&info.netname, sizeof(info.netname));
	arc.Write (&info.team, sizeof(info.team));
	arc << info.aimdist << info.color << info.skin << info.gender << info.neverswitch;
	return arc;
}

FArchive &operator>> (FArchive &arc, userinfo_t &info)
{
	arc.Read (&info.netname, sizeof(info.netname));
	arc.Read (&info.team, sizeof(info.team));
	arc >> info.aimdist >> info.color >> info.skin >> info.gender >> info.neverswitch;
	return arc;
}
