// SauerMod - MODCON - Engine Extensions by Quinton Reeves
// This replaces console.cpp.

VARP(centerblend, 0, 99, 100); // so it doesn't get hooked by hudblend defaults
VARP(centertime, 200, 5000, INT_MAX-1);
VARP(centerlines, 0, 3, 5);

VARP(conblend, 0, 99, 100); // so it doesn't get hooked by hudblend defaults
VARP(contime, 200, 20000, INT_MAX-1);

ICOMMAND(centerprint, "C", console("\f6%s", CON_CENTER, args[0]););

vector<cline> conlines[CN_MAX];

void conline(const char *sf, int n, int type = CON_LEFT)
{
	int _types[] = { CON_LEFT, CON_RIGHT, CON_CENTER };

	loopi(CN_MAX)
	{
		if (type & _types[i])
		{
			cline cl;
			cl.cref = conlines[i].length()>100 ? conlines[i].pop().cref : newstringbuf("");
			cl.outtime = totalmillis;

			int pos = n && i == CN_CENTER ? n : 0;
			conlines[i].insert(pos,cl);

			int c = 0;
			#define addcref(d) { cl.cref[c] = d; c++; }

			if(type & CON_HILIGHT)
			{
				addcref('\f');
				addcref('0');
			}
			if(n && i != CN_CENTER)
			{
				addcref(' ');
				addcref(' ');
				s_strcat(cl.cref, sf);
			}
			
			addcref(0);
			s_strcat(cl.cref, sf);
		}
	}
}

#define CONSPAD (FONTH/3)

void console(const char *s, int type, ...)
{
	extern int scr_w, scr_h;
	int w = screen ? screen->w : scr_w, h = screen ? screen->h : scr_h;
	gettextres(w, h);
	s_sprintfdlv(sf, type, s);
	string sp;
	filtertext(sp, sf);
	puts(sp);
	s = sf;
	int n = 0, visible;
	while((visible = curfont ? text_visible(s, (3*w - 2*CONSPAD - 2*FONTH/3 + FONTW*n)/2) : strlen(s))) // cut strings to fit on screen
	{
		const char *newline = (const char *)memchr(s, '\n', visible);
		if(newline) visible = newline+1-s;
		string t;
		s_strncpy(t, s, visible+1);
		conline(t, n, type);
		s += visible;
		n++;
	}
}

void conoutf(const char *s, ...)
{
	s_sprintfdv(sf, s);
	console("%s", CON_LEFT, sf);
};

int renderconsole(int w, int h)					// render buffer taking into account time & scrolling
{
	if (!menuactive() && centerlines)
	{
		vector<char *> refs;
		refs.setsizenodelete(0);
		loopv(conlines[CN_CENTER]) if(totalmillis-conlines[CN_CENTER][i].outtime<centertime)
		{
			refs.add(conlines[CN_CENTER][i].cref);
			if(refs.length() >= centerlines) break;
		}
		loopvj(refs)
		{
			draw_textx("%s", (w*3)/2, (((h*3)/4)*3)+(FONTH*j)-FONTH, 255, 255, 255, int(255.f*(centerblend*0.01f)), AL_CENTER, refs[j]);
		}
	}

	if(fullconsole)
	{
		int numl = h*3/3/FONTH;
		blendbox(CONSPAD, CONSPAD, w*3-CONSPAD, 2*CONSPAD+numl*FONTH+2*FONTH/3, true);

		loopk(2)
		{
			int offset = min(conskip, max(conlines[k].length() - numl, 0));
			loopi(numl) draw_textx("%s", k ? w*3-(CONSPAD+FONTH/3) : CONSPAD+FONTH/3, CONSPAD+FONTH*(numl-i-1)+FONTH/3, 255, 255, 255, int(255.f*(conblend*0.01f)), k?AL_RIGHT:AL_LEFT, offset+i>=conlines[k].length() ? "" : conlines[k][offset+i].cref); 
		}
		return 2*CONSPAD+numl*FONTH+2*FONTH/3;
	}
	else
	{
		int len = 0;
		loopk(2)
		{
			vector<char *> refs;
			refs.setsizenodelete(0);
			if(consize) loopv(conlines[k]) if(conskip ? i>=conskip-1 || i>=conlines[k].length()-consize : totalmillis-conlines[k][i].outtime<contime)
			{
				refs.add(conlines[k][i].cref);
				if(refs.length()>=consize) break;
			}
			loopvj(refs)
			{
				draw_textx("%s", k ? w*3-(CONSPAD+FONTH/3) : CONSPAD+FONTH/3, CONSPAD+FONTH*(refs.length()-j-1)+FONTH/3, 255, 255, 255, int(255.f*(conblend*0.01f)), k?AL_RIGHT:AL_LEFT, refs[j]);
			}
			if (refs.length() > len) len = refs.length();
		}
		return CONSPAD+len*FONTH+2*FONTH/3;
	}
}

char* getkeyaction(char* keyname)
{
	char* key = newstring(keyname);
	for(char *x = key; *x; x++) *x = toupper(*x);
	loopv(keyms) if (strcmp(keyms[i].name, key) == 0)
	{
		delete key;
		return keyms[i].action;
	}
	delete key;
	return NULL;
}
