/*FTE has some special light editing builtins, I don't ever expect them to be standard or anything, but they're handy for this*/

/*you probably want to change this if you're running hexen2*/
var string autocvar_cg_editor_lightmodel = "progs/s_light.spr";

var float autocvar_r_editlights_import_ambient = 0;
var float autocvar_r_editlights_import_diffuse = 1;
var float autocvar_r_editlights_import_specular = 1;

static float selectedlight;
static float editfield;
static string editvalue;
static entity tempent;
static float helphidden;
void() editor_lights_addentities =
{
	float l;
	if (!tempent)
		tempent = spawn();

	l = (float)dynamiclight_get(-1, -1);
	precache_model(autocvar_cg_editor_lightmodel); /*just to silence it*/
	setmodel(tempent, autocvar_cg_editor_lightmodel);
	while(l > 0)
	{
		l = l-1.0;
		if (l == selectedlight)
		{
			if (gettime(0)*5f & 1)
				continue;
			tempent.effects |= 8192f;
		}
		else
			tempent.effects &~= 8192f;
		if (!(float)dynamiclight_get(l, LFIELD_RADIUS))
			continue;
		setorigin(tempent, dynamiclight_get(l, LFIELD_ORIGIN));
		addentity(tempent);
	}
};

#define NUMLFIELDS 15
#define NUMCMDS 7
static var string fldname[NUMLFIELDS+1+NUMCMDS] = {	"bad",
	"  num",
	"  org",
	"  rgb",
	"  rad",
	"  flg",
	"  sty",
	"  ang",
	"  fov",
	"  cmp",
	 " cor",
	 " csc",
	 " amb",
	 " dif",
	 " spc",
	 " avl",

	"Save",
	"World Lights",
	"Dynamic Lights",
	"Toggle Help",
	"Wipe All",
	"Import",
	"Reload"
};
static string(int fld, float foredit) readfield =
{
	switch(fld)
	{
	case 1:
		if (foredit)
			return ftos(selectedlight);
		return strcat(ftos(selectedlight), " / ", ftos(dynamiclight_get(-1f, -1f)));
	case 2:
		return sprintf("%v", (vector)dynamiclight_get(selectedlight, LFIELD_ORIGIN));
	case 3:
		return sprintf("%v", (vector)dynamiclight_get(selectedlight, LFIELD_COLOUR));
	case 4:
		return ftos(dynamiclight_get(selectedlight, LFIELD_RADIUS));
	case 5:
		float fl = (float)dynamiclight_get(selectedlight, LFIELD_FLAGS);
		string ret;
		ret = strcat(ret, (fl & LFLAG_NORMALMODE)?"d":"");
		ret = strcat(ret, (fl & LFLAG_REALTIMEMODE)?"w":"");
		ret = strcat(ret, (fl & LFLAG_LIGHTMAP)?"l":"");
		ret = strcat(ret, (fl & LFLAG_FLASHBLEND)?"f":"");
		ret = strcat(ret, (fl & LFLAG_NOSHADOWS)?"c":"");
		ret = strcat(ret, (fl & LFLAG_SHADOWMAP)?"s":"");
		ret = strcat(ret, (fl & LFLAG_CREPUSCULAR)?"r":"");
		return ret;
	case 6:
		return ftos(dynamiclight_get(selectedlight, LFIELD_STYLE));
	case 7:
		return sprintf("%v", (vector)dynamiclight_get(selectedlight, LFIELD_ANGLES));
	case 8:
		return ftos(dynamiclight_get(selectedlight, LFIELD_FOV));
	case 9:
		return (string)dynamiclight_get(selectedlight, LFIELD_CUBEMAPNAME);
	case 10:
		return ftos(dynamiclight_get(selectedlight, LFIELD_CORONA));
	case 11:
		return ftos(dynamiclight_get(selectedlight, LFIELD_CORONASCALE));
	case 12:
		return ftos(dynamiclight_get(selectedlight, LFIELD_AMBIENTSCALE));
	case 13:
		return ftos(dynamiclight_get(selectedlight, LFIELD_DIFFUSESCALE));
	case 14:
		return ftos(dynamiclight_get(selectedlight, LFIELD_SPECULARSCALE));
	case 15:
		return sprintf("%v", (vector)dynamiclight_get(selectedlight, LFIELD_ROTATION));
	default:
		return "";
	}
};

static void(float fld, string newval) writefield =
{
	switch(fld)
	{
	case 1:
		selectedlight = stof(newval);
		return;
	case 2:
		dynamiclight_set(selectedlight, LFIELD_ORIGIN, stov(newval));
		return;
	case 3:
		dynamiclight_set(selectedlight, LFIELD_COLOUR, stov(newval));
		return;
	case 4:
		dynamiclight_set(selectedlight, LFIELD_RADIUS, stof(newval));
		return;
	case 5:
		var float fl = 0;
		if (strstrofs(newval, "d")>=0) fl |= LFLAG_NORMALMODE;
		if (strstrofs(newval, "w")>=0) fl |= LFLAG_REALTIMEMODE;
		if (strstrofs(newval, "l")>=0) fl |= LFLAG_LIGHTMAP;
		if (strstrofs(newval, "f")>=0) fl |= LFLAG_FLASHBLEND;
		if (strstrofs(newval, "c")>=0) fl |= LFLAG_NOSHADOWS;
		if (strstrofs(newval, "s")>=0) fl |= LFLAG_SHADOWMAP;
		if (strstrofs(newval, "r")>=0) fl |= LFLAG_CREPUSCULAR;
		dynamiclight_set(selectedlight, LFIELD_FLAGS, (float)fl);
		return;
	case 6:
		dynamiclight_set(selectedlight, LFIELD_STYLE, stof(newval));
		return;
	case 7:
		dynamiclight_set(selectedlight, LFIELD_ANGLES, stov(newval));
		return;
	case 8:
		dynamiclight_set(selectedlight, LFIELD_FOV, stof(newval));
		return;
	case 9:
		dynamiclight_set(selectedlight, LFIELD_CUBEMAPNAME, newval);
		return;
	case 10:
		dynamiclight_set(selectedlight, LFIELD_CORONA, stof(newval));
		return;
	case 11:
		dynamiclight_set(selectedlight, LFIELD_CORONASCALE, stof(newval));
		return;
	case 12:
		dynamiclight_set(selectedlight, LFIELD_AMBIENTSCALE, stof(newval));
		return;
	case 13:
		dynamiclight_set(selectedlight, LFIELD_DIFFUSESCALE, stof(newval));
		return;
	case 14:
		dynamiclight_set(selectedlight, LFIELD_SPECULARSCALE, stof(newval));
		return;
	case 15:
		dynamiclight_set(selectedlight, LFIELD_ROTATION, stov(newval));
		return;
	default:
		return;
	}
};

void(vector m) editor_lights_overlay =
{
	int i;
	string s;
	vector col;

	m_y = floor((m_y - 32f) / 8f);


	fldname[NUMLFIELDS+2] = strcat("realtime world: ", cvar("r_shadow_realtime_world")?"on":"off");
	fldname[NUMLFIELDS+3] = strcat("realtime dlight: ", cvar("r_shadow_realtime_dlight")?"on":"off");

	for (i = 1; i <= NUMLFIELDS; i++)
	{
		if (editfield == i)
			s = editvalue;
		else
			s = readfield(i, 0);
		s = strcat(ftos(i), " ", fldname[i], ": ", s);

		if (editfield == i)
			col = '1 0 0';
		else if (m_y == i && m_x < 64)
			col = '0 0 1';
		else
			col = '1 1 1';
			
		drawrawstring('0 32 0' + '0 8 0' * (float)i, s, '8 8 0', col, 1);
	}

	for (i = NUMLFIELDS+1f; i <= NUMLFIELDS+NUMCMDS; i+=1)
	{
		s = strcat(ftos(i), " ", fldname[i]);

		if (editfield == i)
			col = '1 0 0';
		else if (m_y == i && m_x < 64)
			col = '0 0 1';
		else
			col = '1 1 1';
			
		drawrawstring('0 32 0' + '0 8 0' * (float)i, s, '8 8 0', col, 1);
	}
	i+=1i;

	if (helphidden)
		return;

	if (editfield == 5)
	{
		drawrawstring('0 32 0' + '0 8 0' * (float)i, "d: dynamic mode\n", '8 8 0', '1 1 1', 1); i+=1i;
		drawrawstring('0 32 0' + '0 8 0' * (float)i, "w: realtime world lights mode\n", '8 8 0', '1 1 1', 1); i+=1i;
		drawrawstring('0 32 0' + '0 8 0' * (float)i, "l: lightmap hack (not valid above index 32)\n", '8 8 0', '1 1 1', 1); i+=1i;
		drawrawstring('0 32 0' + '0 8 0' * (float)i, "f: flashblend coronas\n", '8 8 0', '1 1 1', 1); i+=1i;
		drawrawstring('0 32 0' + '0 8 0' * (float)i, "c: does not cast shadows\n", '8 8 0', '1 1 1', 1); i+=1i;
		drawrawstring('0 32 0' + '0 8 0' * (float)i, "s: shadowmapped light\n", '8 8 0', '1 1 1', 1); i+=1i;
		drawrawstring('0 32 0' + '0 8 0' * (float)i, "r: crepuscular rays\n", '8 8 0', '1 1 1', 1); i+=1i;
	}
	else
	{
		drawrawstring('0 32 0' + '0 8 0' * (float)i, "+/- change selected light\n", '8 8 0', '1 1 1', 1); i+=1i;
		drawrawstring('0 32 0' + '0 8 0' * (float)i, "mouse also selects lights\n", '8 8 0', '1 1 1', 1);	i+=1i;
		drawrawstring('0 32 0' + '0 8 0' * (float)i, "m moves the light to the cursor\n", '8 8 0', '1 1 1', 1); i+=1i;
		drawrawstring('0 32 0' + '0 8 0' * (float)i, "i inserts new light\n", '8 8 0', '1 1 1', 1); i+=1i;
		drawrawstring('0 32 0' + '0 8 0' * (float)i, "@ sets the light's radius to the cursor\n", '8 8 0', '1 1 1', 1); i+=1i;
		drawrawstring('0 32 0' + '0 8 0' * (float)i, "# changes the light's shadow flag\n", '8 8 0', '1 1 1', 1); i+=1i;
		drawrawstring('0 32 0' + '0 8 0' * (float)i, "p points the light to aim at the cursor\n", '8 8 0', '1 1 1', 1); i+=1i;
		drawrawstring('0 32 0' + '0 8 0' * (float)i, "[ and ] move the light towards/away from indicated plane\n", '8 8 0', '1 1 1', 1); i+=1i;
		drawrawstring('0 32 0' + '0 8 0' * (float)i, "don't forget to save\n", '8 8 0', '1 1 1', 1); i+=1i;
	}
};

static void(vector fwd, vector vorg) selectbestlight =
{
	float l, b=selectedlight, d, bd;
	vector ldir;
	l = (float)dynamiclight_get(-1f, -1f);
	bd = 0;
	while(l > 0)
	{
		l-=1;
		ldir = (vector)dynamiclight_get(l, LFIELD_ORIGIN);
		ldir = normalize(ldir - vorg);
		d = fwd*ldir;
		if (d > bd)
		{
			bd = d;
			b = l;
		}
	}
	selectedlight = b;
};

float(float keyc, float unic, vector m) editor_lights_key =
{
	vector t = unproject(m + '0 0 8192');
	vector o = unproject(m);
	string ns;
	if (keyc == 512 || (!editfield && unic == 13 && m_x < 64))
	{
		if (editfield)
		{
			writefield(editfield, editvalue);
			strunzone(editvalue);
			editfield = 0;
		}
		editfield = floor((m_y - 32f) / 8f);
		if (editfield <= 0 || editfield > NUMLFIELDS+NUMCMDS || m_x >= 64)
		{
			editfield = 0;

			selectbestlight(t - o, o);
		}
		else if (editfield > NUMLFIELDS)
		{
			switch(editfield - (NUMLFIELDS+1))
			{
			case 0:
				localcmd("r_editlights_save\n");
				break;
			case 1:
				localcmd("toggle r_shadow_realtime_world\n");
				break;
			case 2:
				localcmd("toggle r_shadow_realtime_dlight\n");
				break;
			case 3:
				helphidden = !helphidden;
				break;
			case 4:
				localcmd("r_editlights_reload none\n");
				break;
			case 5:
				localcmd("r_editlights_reload bsp\n");
				break;
			case 6:
				localcmd("r_editlights_reload\n");
				break;
			}
			editfield = 0;
		}
		else
			editvalue = strzone(readfield(editfield, 1));
	}
	else if (editfield)
	{
		ns = strcat(editvalue);
		if (keyc == 10 || keyc == 13)
		{
			writefield(editfield, ns);
			editfield = 0;
		}
		else if (keyc == 127)
		{
			if (ns != "")
				ns = substring(ns, 0, -2);
		}
		else if (keyc == 8)
		{
			ns = "";
		}
		else
			ns = strcat(ns, chr2str(unic));

		ns = strzone(ns);
		strunzone(editvalue);
		editvalue = ns;

		writefield(editfield, ns);
	}
	else if (unic >= '0' && unic <= '9')
	{
		editfield = unic - '0';
		editvalue = strzone(readfield(editfield, 1));
	}
	else if (unic == '=')
		selectedlight++;
	else if (unic == '-')
		selectedlight-=1;
	else if (unic == 'n' || unic == 'N')
		localcmd("noclip\n");
//	else if (unic == 's' || unic == 'S')
//	{
//		selectbestlight(t - o, o);
//	}
	else if (unic == 'm' || unic == 'M')
	{
		traceline(o, t, TRUE, world);
		dynamiclight_set(selectedlight, LFIELD_ORIGIN, trace_endpos + trace_plane_normal*4);
	}
	else if (unic == 'p' || unic == 'P')
	{
		traceline(o, t, TRUE, world);
		vector ang = vectoangles((trace_endpos + trace_plane_normal*4f) - (vector)dynamiclight_get(selectedlight, LFIELD_ORIGIN));
		ang_x *= -1f;
		dynamiclight_set(selectedlight, LFIELD_ANGLES, ang);

		/*if we're pointing the light at something, it should probably have a fov*/
		if (!(float)dynamiclight_get(selectedlight, LFIELD_FOV))
			dynamiclight_set(selectedlight, LFIELD_FOV, 90f);
	}
	else if (unic == 'i' || unic == 'I')
	{
		float oldl = selectedlight;
		for (selectedlight = 32; ; selectedlight+=1)
		{
			if (!(float)dynamiclight_get(selectedlight, LFIELD_RADIUS))
			{
				if (oldl >= 32 && (!((float)dynamiclight_get(selectedlight, LFIELD_RADIUS) > 50)))
				{
					/*dupe the current light*/
					dynamiclight_set(selectedlight, LFIELD_RADIUS,		dynamiclight_get(oldl, LFIELD_RADIUS));
					dynamiclight_set(selectedlight, LFIELD_COLOUR,		dynamiclight_get(oldl, LFIELD_COLOUR));
					dynamiclight_set(selectedlight, LFIELD_FOV,		dynamiclight_get(oldl, LFIELD_FOV));
					dynamiclight_set(selectedlight, LFIELD_STYLE,		dynamiclight_get(oldl, LFIELD_STYLE));
					dynamiclight_set(selectedlight, LFIELD_ANGLES,		dynamiclight_get(oldl, LFIELD_ANGLES));
					dynamiclight_set(selectedlight, LFIELD_FLAGS,		dynamiclight_get(oldl, LFIELD_FLAGS));
					dynamiclight_set(selectedlight, LFIELD_AMBIENTSCALE,	dynamiclight_get(oldl, LFIELD_AMBIENTSCALE));
					dynamiclight_set(selectedlight, LFIELD_DIFFUSESCALE,	dynamiclight_get(oldl, LFIELD_DIFFUSESCALE));
					dynamiclight_set(selectedlight, LFIELD_SPECULARSCALE,	dynamiclight_get(oldl, LFIELD_SPECULARSCALE));
					dynamiclight_set(selectedlight, LFIELD_CUBEMAPNAME,	dynamiclight_get(oldl, LFIELD_CUBEMAPNAME));
					dynamiclight_set(selectedlight, LFIELD_CORONA,		dynamiclight_get(oldl, LFIELD_CORONA));
					dynamiclight_set(selectedlight, LFIELD_CORONASCALE,	dynamiclight_get(oldl, LFIELD_CORONASCALE));
					dynamiclight_set(selectedlight, LFIELD_ROTATION,	dynamiclight_get(oldl, LFIELD_ROTATION));
				}
				else
				{
					/*reset the light's properties*/
					dynamiclight_set(selectedlight, LFIELD_RADIUS, 300);
					dynamiclight_set(selectedlight, LFIELD_COLOUR, '1 1 1');
					dynamiclight_set(selectedlight, LFIELD_FOV, 0);
					dynamiclight_set(selectedlight, LFIELD_STYLE, 0);
					dynamiclight_set(selectedlight, LFIELD_ANGLES, '0 0 0');
					dynamiclight_set(selectedlight, LFIELD_FLAGS, LFLAG_REALTIMEMODE);
					dynamiclight_set(selectedlight, LFIELD_AMBIENTSCALE, autocvar_r_editlights_import_ambient);
					dynamiclight_set(selectedlight, LFIELD_DIFFUSESCALE, autocvar_r_editlights_import_diffuse);
					dynamiclight_set(selectedlight, LFIELD_SPECULARSCALE, autocvar_r_editlights_import_specular);
					dynamiclight_set(selectedlight, LFIELD_CUBEMAPNAME,	"");
					dynamiclight_set(selectedlight, LFIELD_CORONA,		0);
					dynamiclight_set(selectedlight, LFIELD_CORONASCALE,	1);
					dynamiclight_set(selectedlight, LFIELD_ROTATION,	'0 0 0');
				}

				/*place it at the pointed location*/
				traceline(o, t, TRUE, world);
				dynamiclight_set(selectedlight, LFIELD_ORIGIN, trace_endpos + trace_plane_normal*4f);
				break;
			}
		}
	}
	else if (unic == '[')
	{
		traceline(o, t, TRUE, world);
		dynamiclight_set(selectedlight, LFIELD_ORIGIN, (vector)dynamiclight_get(selectedlight, LFIELD_ORIGIN) - trace_plane_normal);
	}
	else if (unic == ']')
	{
		traceline(o, t, TRUE, world);
		dynamiclight_set(selectedlight, LFIELD_ORIGIN, (vector)dynamiclight_get(selectedlight, LFIELD_ORIGIN) + trace_plane_normal);
	}
	else if (unic == '\'' || unic == '@')
	{
		traceline(o, t, TRUE, world);
		dynamiclight_set(selectedlight, LFIELD_RADIUS, 1.5*vlen(trace_endpos - (vector)dynamiclight_get(selectedlight, LFIELD_ORIGIN)));
	}
	else if (unic == '#')
	{
		float fl;
		fl = (float)dynamiclight_get(selectedlight, LFIELD_FLAGS);
		if (fl & LFLAG_NOSHADOWS)
			fl -= LFLAG_NOSHADOWS;
		else
			fl += LFLAG_NOSHADOWS;
		dynamiclight_set(selectedlight, LFIELD_FLAGS, (float)fl);
	}
	else if (unic == '{')
		dynamiclight_set(selectedlight, LFIELD_RADIUS, dynamiclight_get(selectedlight, LFIELD_RADIUS) - 15);
	else if (unic == '}')
		dynamiclight_set(selectedlight, LFIELD_RADIUS, dynamiclight_get(selectedlight, LFIELD_RADIUS) + 15);
	else if (keyc == 127)
		dynamiclight_set(selectedlight, LFIELD_RADIUS, 0);
	else
		return FALSE;
	return TRUE;
};
