#include "rpggame.h"

namespace game
{
	bool needminimap() { return curmap; }

	void quad(int x, int y, int xs, int ys)
	{
		glBegin(GL_TRIANGLE_STRIP);
		glTexCoord2f(0, 0); glVertex2i(x,    y);
		glTexCoord2f(1, 0); glVertex2i(x+xs, y);
		glTexCoord2f(0, 1); glVertex2i(x,    y+ys);
		glTexCoord2f(1, 1); glVertex2i(x+xs, y+ys);
		glEnd();
	}

	float abovegameplayhud(int w, int h)
	{
		if(editmode || game::ispaused()) return 1;

		return 1350.f / 1600.f;
	}

	int clipconsole(int w, int h)
	{
		return 0;
	}

	const char *defaultcrosshair(int index)
	{
		return editmode ? "packages/crosshairs/edit" : "packages/crosshairs/default";
	}

	int selectcrosshair(float &r, float &g, float &b)
	{
		if(editmode)
		{
			r = b = 0.5;
		}
		return editmode;
	}

	VARP(minimapmaxdist, 128, 1536, 16384);
	FVARP(minimapfrac, .1, .5, 1);
	VARP(minimapup, 0, 1, 1);
	VARP(minimap, 0, 1, 1);

	void drawminimap(reference *ent, float x, float y, float dx, float dy)
	{
		const int coords[4][2] = { {0,0}, {1, 0}, {1, 1}, {0,1}};
		if(!minimap || !ent || !ent->getent()) return;
		rpgent *d = ent->getent();
		float offset = min<float>(getworldsize() * minimapfrac / 2.0f, minimapmaxdist);

		glPushMatrix();
		glTranslatef(x + dx / 2, y + dy / 2, 0);
		glDisable(GL_BLEND);
		if(minimapup) glRotatef(d->yaw + 180, 0, 0, -1);

		if(curmap->flags & mapinfo::F_NOMINIMAP)
		{
			glColor3f(0, 0, 0);
			glDisable(GL_TEXTURE_2D);
			glBegin(GL_TRIANGLE_FAN);
			loopi(16)
			{
				vec dir(M_PI / 8 * i, 0);
				glVertex2i(x + dir.x * dx / 2, y + dir.y * dy / 2);
			}
			glEnd();
			glEnable(GL_TEXTURE_2D);
			glEnable(GL_BLEND);

			settexture("data/rpg/hud/player", 3);
			glBegin(GL_TRIANGLE_FAN);
			loopi(4)
			{
				vec dir((d->yaw) * RAD + M_PI * i / 2.0f, 0);
				glTexCoord2f(coords[i][0], coords[i][1]);
				glVertex2i(dx / 16 * dir.x, dy / 16 * dir.y);
			}
			glEnd();
		}
		else
		{
			vec pos = vec(d->o).sub(minimapcenter).mul(minimapscale).add(.5f);
			glColor3f(1, 1, 1);
			bindminimap();
			glBegin(GL_TRIANGLE_FAN);
			loopi(16)
			{
				vec dir(M_PI / 8 * i, 0);
				glTexCoord2f(pos.x + dir.x * offset * minimapscale.x, pos.y + dir.y * offset * minimapscale.y);
				glVertex2i(dx * dir.x / 2, dy * dir.y / 2);
			}
			glEnd();
			glEnable(GL_BLEND);

			settexture("data/rpg/hud/player", 3);
			glBegin(GL_QUADS);
			loopv(curmap->objs)
			{
				rpgent *m = curmap->objs[i];
				vec pos = vec(m->o).sub(d->o).div(offset); pos.z = 0;
				vec col = m->blipcol();

				if(pos.magnitude() >= 1) continue;

				glColor4f(col.x, col.y, col.z, 3 - 3 * pos.magnitude());

				loopi(4)
				{
					vec dir((m->yaw) * RAD + M_PI * i / 2.0f, 0);
					glTexCoord2f(coords[i][0], coords[i][1]);
					glVertex2i(pos.x * dx / 2 + dx / 24 * dir.x, pos.y * dy / 2 + dy / 24 * dir.y);
				}
			}
			glEnd();

			settexture("data/rpg/hud/blip", 3);
			glBegin(GL_QUADS);
			loopv(curmap->projs)
			{
				projectile &p = *curmap->projs[i];
				vec pos = vec(p.o).sub(d->o).div(offset); pos.z = 0;
				if(pos.magnitude() >= 1)
					continue;

				glColor4f(p.owner != d, p.owner == d, 0, min<float>(1, 3 - 3 * pos.magnitude()));

				glTexCoord2i(0, 0);
				glVertex2i(pos.x * dx / 2 - dx / 64, pos.y * dy / 2 - dy / 64);
				glTexCoord2i(1, 0);
				glVertex2i(pos.x * dx / 2 + dx / 64, pos.y * dy / 2 - dy / 64);
				glTexCoord2i(1, 1);
				glVertex2i(pos.x * dx / 2 + dx / 64, pos.y * dy / 2 + dy / 64);
				glTexCoord2i(0, 1);
				glVertex2i(pos.x * dx / 2 - dx / 64, pos.y * dy / 2 + dy / 64);
			}

			//TODO loopv(curmap->blips) {}
			glEnd();
		}

		glColor3f(1, 1, 1);
		settexture("data/rpg/hud/compass", 3);
		quad(-dx / 2 - 2, -dy / 2 - 2, dx + 4, dy + 4);
		glPopMatrix();
	}
	ICOMMAND(r_hud_minimap, "sffff", (const char *r, float *x, float *y, float *dx, float *dy),
		reference *ent = rpgscript::searchstack(r);
		drawminimap(ent, *x, *y, *dx, *dy);
	)

	void drawhorizbar(const char *img, float x, float y, float dx, float dy, float progress, int colour)
	{
		vec col((colour >> 16) & 255, (colour >> 8) & 255, colour & 255);
		col.div(255.f);

		settexture(*img ? img : "data/rpg/hud/hbar", 3);
		glBegin(GL_TRIANGLE_FAN);

		glColor3fv(col.v);
		glTexCoord2f(0, 0);        glVertex2i(x , y);
		glTexCoord2f(progress, 0); glVertex2i(x + dx * progress, y);
		glTexCoord2f(progress, 1); glVertex2i(x + dx * progress, y + dy);
		glTexCoord2f(0, 1);        glVertex2i(x, y + dy);

		glEnd();
	}
	ICOMMAND(r_hud_horizbar, "sfffffii", (const char *i, float *x, float *y, float *dx, float *dy, float *p, int *col),
		drawhorizbar(i, *x, *y, *dx, *dy, *p, *col);
	)

	void drawvertbar(const char *img, float x, float y, float dx, float dy, float progress, int colour)
	{
		vec col((colour >> 16) & 255, (colour >> 8) & 255, colour & 255);
		col.div(255.f);

		settexture(*img ? img : "data/rpg/hud/vbar", 3);
		glBegin(GL_TRIANGLE_FAN);

		glColor3fv(col.v);
		glTexCoord2f(0, 0);        glVertex2i(x , y);
		glTexCoord2f(1, 0);        glVertex2i(x + dx, y);
		glTexCoord2f(1, progress); glVertex2i(x + dx, y + dy * progress);
		glTexCoord2f(0, progress); glVertex2i(x, y + dy * progress);

		glEnd();
	}
	ICOMMAND(r_hud_vertbar, "sfffffi", (const char *i, float *x, float *y, float *dx, float *dy, float *p, int *col),
		drawvertbar(i, *x, *y, *dx, *dy, *p, *col);
	)

	void drawtext(float x, float y, float size, int colour, const char *str)
	{
		glPushMatrix();
		glTranslatef(x, y, 0);
		glScalef(size, size, size);

		vec col((colour >> 16) & 255, (colour >> 8) & 255, colour & 255);
		draw_text(str, 0, 0, col.x, col.y, col.z);

		glPopMatrix();
	}
	ICOMMAND(r_hud_text, "fffis", (float *x, float *y, float *sz, int *col, const char *s),
		drawtext(*x, *y, *sz, *col, s);
	)

	void drawimage(const char *img, float x, float y, float dx, float dy, int colour)
	{
		settexture(img, 3);
		vec col = vec((colour >> 16) & 255, (colour >> 8) & 255, colour & 255).div(255.f);

		glColor3fv(col.v);
		quad(x, y, dx, dy);
	}
	ICOMMAND(r_hud_image, "sffffi", (const char *i, float *x, float *y, float *dx, float *dy, int *c),
		drawimage(i, *x, *y, *dx, *dy, *c);
	)

	void drawsolid(float x, float y, float dx, float dy, int colour)
	{
		glDisable(GL_TEXTURE_2D);
		vec col = vec((colour >> 16) & 255, (colour >> 8) & 255, colour & 255).div(255.f);

		glColor3fv(col.v);
		quad(x, y, dx, dy);
		glEnable(GL_TEXTURE_2D);
	}

	ICOMMAND(r_hud_solid, "ffffi", (float *x, float *y, float *dx, float *dy, int *c),
		drawsolid(*x, *y, *dx, *dy, *c);
	)

	const uint *hud = NULL;
	FVAR(hud_right, 1, 0, -1);
	FVAR(hud_bottom, 1, 0, -1);

	ICOMMAND(r_hud, "s", (const char *body),
		delete[] hud;
		hud = compilecode(body);
	)

	void gameplayhud(int w, int h)
	{
		if(!mapdata || !curmap || rpggui::open())
			return;

		glPushMatrix();
		float scale = min (w / 1600.0f, h / 1200.0f);
		glScalef(scale, scale, 1);

		hud_right = w / scale, hud_bottom = h / scale; // top and left are ALWAYS 0

		if(camera::cutscene)
		{
			camera::render(ceil(hud_right), ceil(hud_bottom));
			glPopMatrix();
			return;
		}

		if(hud) execute(hud);

		if(DEBUG_WORLD)
		{
			glPushMatrix();
			glTranslatef(hud_right - 300, 350, 0);
			glScalef(.5, .5, .5);

			draw_textf("curmap: %s", 0, 0, curmap->name);
			draw_textf("blips: %i", 0, 50, curmap->blips.length());
			draw_textf("entities: %i", 0, 100, curmap->objs.length());
			draw_textf("persistent effects: %i", 0, 150, curmap->aeffects.length());
			draw_textf("projectiles: %i", 0, 200, curmap->projs.length());

			glPopMatrix();
		}

		glPopMatrix();
	}
}
