#pragma once

USING(ArrayList, entity);
.int al_buf;
.int al_len;

#define AL_NEW(this, n, default, T) MACRO_BEGIN \
	ArrayList _al = this = new_pure(ArrayList); \
	_al.al_buf = buf_create(); \
	for (int i = 0, _n = _al.al_len = n; i < _n; ++i) \
	{ \
		const _AL_type__##T() it = default; \
		AL_set##T(this, i, it); \
	} \
MACRO_END

#define AL_DELETE(this) MACRO_BEGIN \
	buf_del(this.al_buf); \
	delete(this); \
	this = NULL; \
MACRO_END

#define _AL_type__s() string
#define AL_gets(this, idx) bufstr_get(this.al_buf, idx)
#define AL_sets(this, idx, val) bufstr_set(this.al_buf, idx, val)

#ifdef CSQC
string al_ftos(float f) = #26;
float al_stof(string s) = #81;
#elifdef SVQC
string al_ftos(float f) = #26;
float al_stof(string s) = #81;
#elifdef MENUQC
string al_ftos(float f) = #17;
float al_stof(string s) = #21;
#endif

#define _AL_type__f() float
#define AL_getf(this, idx) al_stof(AL_gets(this, idx))
#define AL_setf(this, idx, val) AL_sets(this, idx, al_ftos(val))

#ifdef CSQC
int al_etof(entity e) = #512;
entity al_ftoe(int i) = #459;
#elifdef SVQC
int al_etof(entity e) = #512;
entity al_ftoe(int i) = #459;
#elifdef MENUQC
int al_etof(entity e) = #79;
entity al_ftoe(int i) = #80;
#endif

#define _AL_type__e() entity
#define AL_gete(this, idx) al_ftoe(AL_getf(this, idx))
#define AL_sete(this, idx, val) AL_setf(this, idx, al_etof(val))

#define AL_EACH(this, T, cond, body) MACRO_BEGIN \
	const noref ArrayList _al = this; \
	for (int i = 0, n = _al.al_len; i < n; ++i) \
	{ \
		const noref _AL_type__##T() it = AL_get##T(_al, i); \
		if (cond) \
			LAMBDA(body) \
	} \
MACRO_END
