#include "act.qh"

#include "common.qh"

#include "items.qh"
#include "damage.qh"
#include "misc.qh"
#include "teleport.qh"

#include "override.qh"

.entity overrider, overrider_self;
.float overrider_priority;

// ===================================================================== //

/* Let's make my life simpler when I add new ones, mmmkay? */
#define all_funcs()								\
	one_func(float (), f_v, th_takeitem, (), return, FALSE);			\
										\
	one_func(void (entity missile), v_e, th_attack, (missile), , );		\
										\
	one_func(float (float dmg), f_f, th_takedamage, (dmg), return, FALSE);	\
	one_func(float (float dmg), f_f, th_dealdamage, (dmg), return, dmg);	\
										\
	one_func(void (), v_v, th_die, (), , );					\
	one_func(void (), v_v, th_kill, (), , );					\
										\
	one_func(void (), v_v, prethink, (), , );				\
	one_func(void (), v_v, actthink, (), , );				\
	one_func(void (), v_v, postthink, (), , );				\
										\
	one_func(float (vector org), f_c, th_teleport, (org), return, TRUE);	\
										\
	one_func(float (entity missile), f_e, th_projectile, (missile), return, TRUE)


#define all_types()								\
	one_type (void (), v_v);							\
	one_type (float (), f_v);							\
	one_type (void (entity ent), v_e);					\
	one_type (float (float flt), f_f);					\
	one_type (float (vector vec), f_c);					\
	one_type (float (entity ent), f_e)

// ===================================================================== //

/* default passthru functions */
#define one_func(type1,type2,func,args,return,val)	\
type1 _passthru_##func = {				\
	local entity ovr;				\
	ovr = override_findself ();			\
	if (ovr.func)					\
		return ovr.func args;			\
	return val;					\
}

all_funcs();

#undef one_func

/* for the override_set_FUNCTION macros in override.qh */
#define one_type(type1,type2)						\
	void(entity e, .type1 fld, type1 func) override_set_##type2 = {	\
		if (e.overrider)					\
			e.overrider.fld = func;				\
		else							\
			e.fld = func;					\
}

all_types ();

#undef one_type

// ===================================================================== //

void (entity e1, entity e2)
_override_swap =
{
#define one_type(type1,type2)		local type1 t_##type2
	all_types();
#undef one_type

	/* Swap all the functions */
#define one_func(type1,type2,func,args,return,val)	\
	t_##type2 = e1.func;			\
	e1.func = e2.func;			\
	e2.func = t_##type2

	all_funcs();
#undef one_func
};

// ===================================================================== //

entity (entity e, string override_class, float priority)
override_create =
{
	local entity ovr, ovr2;

	for (ovr = e.overrider; ovr; ovr = ovr.overrider) {
		if (ovr.classname == override_class) {
			ovr2 = ovr.overrider;
			if (!ovr2)
				ovr2 = e;
			_override_swap (ovr, ovr2);
			return ovr;
		}
	}

	/* Move to the tail.. */
	for (ovr = e; ovr.overrider; ovr = ovr.overrider) {
		if (ovr.overrider.overrider_priority > priority)
			break;
	}

	ovr2 = ovr.overrider;
	ovr.overrider = spawn(override_class);
	ovr.overrider.owner = ovr;
	ovr.overrider.overrider = ovr2;

	if (ovr2)
		ovr2.owner = ovr.overrider;
	if (!ovr2)
		ovr2 = e;

	ovr = ovr.overrider;
	ovr.overrider_priority = priority;
	ovr.goalentity = ovr2;

	/* Set default passthru funcs for ovr */
#define one_func(type1,type2,func,args,return,val)	\
	ovr.func = _passthru_##func

	all_funcs ();
#undef one_func

	return ovr;
};

void (entity ovr)
override_finalize =
{
	_override_swap (ovr, ovr.goalentity);
};

entity ()
override_findself =
{
	local entity ovrself;

	ovrself = self.overrider_self;
	if (!ovrself) {
		/* Move to the end of the list */
		for (ovrself = self.overrider; ovrself.overrider;
			 ovrself = ovrself.overrider);
	}

	self.overrider_self = ovrself.owner;
	if (self.overrider_self == self)
		self.overrider_self = world;
	
	return ovrself;
};

void ()
override_halt =
{
	self.overrider_self = world;
};

void (entity e, entity ovr)
override_destroy =
{
	local entity ovr2;

	ovr2 = ovr.overrider;
	if (!ovr2)
		ovr2 = e;

	/* Copy the funcs from ovr to ovr2 */
#define one_func(type1,type2,func,args,return,val)	\
	ovr2.func = ovr.func

	all_funcs();
#undef one_func

	if (ovr.overrider)
		ovr.overrider.owner = ovr.owner;
	ovr.owner.overrider = ovr.overrider;

	ovr.think = SUB_remove;
	ovr.nextthink = time;
};
