#ifndef __HOVERBIKE_H__
#define __HOVERBIKE_H__

#include "g_local.h"
#include "entity.h"
#include "misc.h"

// weapon defines
#define NUM_HOVERWEAPONS	3
#define HWMODE_ROCKETS		0
#define HWMODE_CHAINGUN		1
#define HWMODE_MINES		2

// guage defines
#define HBGUAGE_SPEEDBAR	1
#define HBGUAGE_SPEEDNUM	2
#define HBGUAGE_TURBOBAR	3
#define HBGUAGE_HEALTHBAR	4
#define HBGUAGE_AMMONUM		5
#define HBGUAGE_WEAPONICON	6

// rider type defines
typedef enum
{
	RIDER_OTHER,
	RIDER_PLAYER,
	RIDER_BOT // hint hint ;)
} ridertype_t;

// the extra bounding boxes for a hoverbike
class HoverbikeBox : public Entity
{
public:
	float offset; // forward offset from the main hoverbike entity
	EntityPtr bike; // pointer to owner hoverbike

	CLASS_PROTOTYPE(HoverbikeBox);

	HoverbikeBox();
	virtual void BikeUse(Event *ev);
	virtual void BikeDamage(Event *ev);

	virtual void Archive(Archiver &arc);
	virtual void Unarchive(Archiver &arc);
};

inline void HoverbikeBox::Archive (Archiver &arc)
{
	Entity::Archive( arc );

	arc.WriteFloat(offset);
	arc.WriteSafePointer(bike);
}

inline void HoverbikeBox::Unarchive (Archiver &arc)
{
	Entity::Unarchive( arc );

	offset = arc.ReadFloat();
	arc.ReadSafePointer(&bike);
}

/*template class SafePtr<HoverbikeBox>;*/
typedef SafePtr<HoverbikeBox> HoverbikeBoxPtr;

// control guages
class HoverbikeGuage : public Entity
{
private:
	int guagetype; // the kind of guage that it is

public:
	CLASS_PROTOTYPE(HoverbikeGuage);

	virtual void Setup(Entity *owner, int type);
	virtual void SetValue(int value);

	virtual void Archive(Archiver &arc);
	virtual void Unarchive(Archiver &arc);
};

inline void HoverbikeGuage::Archive (Archiver &arc)
{
	Entity::Archive( arc );

	arc.WriteInteger(guagetype);
}

inline void HoverbikeGuage::Unarchive (Archiver &arc)
{
	Entity::Unarchive( arc );

	guagetype = arc.ReadInteger();
}

/*template class SafePtr<HoverbikeGuage>;*/
typedef SafePtr<HoverbikeGuage> HoverbikeGuagePtr;

class Player;

class Hoverbike : public Entity
{
public:
	HoverbikeBoxPtr frontbox; // pointer to front bounding box
	HoverbikeBoxPtr backbox; // pointer to back bounding box

	EntityPtr rider; // pointer to riding player
	ridertype_t ridertype; // set to quickly tell what kind of rider we have

	HoverbikeGuagePtr speed_bar;
	HoverbikeGuagePtr speed_number;
	HoverbikeGuagePtr turbo_bar;
	HoverbikeGuagePtr health_bar;
	HoverbikeGuagePtr ammo_number;
	HoverbikeGuagePtr weapon_icon;

	Vector spawnspot; // place where it was spawned
	Vector spawnangles; // angles at which it was spawned
	float respawntimer; // timmer for respawning
	float damagetimer;
	float getontimer; // use debounce timer for when getting on

	float bobsin; // for rider view bobbing
	float bobfrac; // for rider view bobbing

	EntityPtr oldweapon;
	int rockets;
	int bullets;
	int mines;

	float forwardmove;
	float sidemove;
	float upmove;

	Vector move_angles;
	float airpitch_timmer;
	float speed;
	int forward_speed;
	float strafingroll;
	float boosttimmer;
	float turbo;

	int weaponmode; // bike's current weapon mode

	int sndflags; // hovering sound flags
	str currsound; // alias of current hovering sound

	float effectstimmer;
	float soundtimmer;

	CLASS_PROTOTYPE(Hoverbike);

	Hoverbike();

	virtual void RespawnSetup(Vector spot, Vector ang, float respawndelay, int grav, int flags);
	virtual void BikeRespawn(Event *ev);

	virtual void SetRiderAngles(Vector angles);
	virtual void SetRiderYaw(float yawangle);
	virtual void BikeUse(Event *ev);
	virtual void BikeGetOff(void);
	virtual void BikePain(Event *ev);
	virtual void BikeKilled(Event *ev);
	virtual void GiveExtraFrag(Entity *attacker);

	virtual qboolean Ride(usercmd_t *ucmd);
	virtual void RiderMove(usercmd_t *ucmd);
	virtual void Postthink(void);
	virtual void Hover(void);
	virtual void ApplyControls(void);
	virtual void ApplyMoveAngles(void);
	void SetGravityAxis(int axis);

	virtual void WeaponChangeSound(void);
	virtual void WeaponNoAmmoSound(void);
	virtual void SetHoverSound(void);
	virtual void CollisionSound(Vector before, Vector after);

	virtual void NextWeapon(void);
	virtual void PreviousWeapon(void);
	virtual void SelectWeapon(int weapon);

	virtual void MakeGuages(void);
	virtual void KillGuages(void);
	virtual void UpdateGuages(void);
	virtual void GuagesViewerOn(void);
	virtual void GuagesViewerOff(void);

	virtual void Archive(Archiver &arc);
	virtual void Unarchive(Archiver &arc);
};

inline void Hoverbike::Archive (Archiver &arc)
{
	Entity::Archive( arc );

	arc.WriteSafePointer(frontbox);
	arc.WriteSafePointer(backbox);

	arc.WriteSafePointer(rider);
	arc.WriteInteger(ridertype);

	arc.WriteSafePointer(speed_bar);
	arc.WriteSafePointer(speed_number);
	arc.WriteSafePointer(turbo_bar);
	arc.WriteSafePointer(health_bar);
	arc.WriteSafePointer(ammo_number);
	arc.WriteSafePointer(weapon_icon);

	arc.WriteVector(spawnspot);
	arc.WriteVector(spawnangles);
	arc.WriteFloat(respawntimer);
	arc.WriteFloat(damagetimer);
	arc.WriteFloat(getontimer);

	arc.WriteFloat(bobsin);
	arc.WriteFloat(bobfrac);

	arc.WriteSafePointer(oldweapon);
	arc.WriteInteger(rockets);
	arc.WriteInteger(bullets);
	arc.WriteInteger(mines);

	arc.WriteFloat(forwardmove);
	arc.WriteFloat(sidemove);
	arc.WriteFloat(upmove);

	arc.WriteVector(move_angles);
	arc.WriteFloat(airpitch_timmer);
	arc.WriteFloat(speed);
	arc.WriteInteger(forward_speed);
	arc.WriteFloat(strafingroll);
	arc.WriteFloat(boosttimmer);
	arc.WriteFloat(turbo);

	arc.WriteInteger(weaponmode);

	arc.WriteInteger(sndflags);
	arc.WriteString(currsound);

	arc.WriteFloat(effectstimmer);
	arc.WriteFloat(soundtimmer);
}

inline void Hoverbike::Unarchive (Archiver &arc)
{
	int temp;

	Entity::Unarchive( arc );

	arc.ReadSafePointer(&frontbox);
	arc.ReadSafePointer(&backbox);

	arc.ReadSafePointer(&rider);
	temp = arc.ReadInteger();
	ridertype = (ridertype_t)temp;

	arc.ReadSafePointer(&speed_bar);
	arc.ReadSafePointer(&speed_number);
	arc.ReadSafePointer(&turbo_bar);
	arc.ReadSafePointer(&health_bar);
	arc.ReadSafePointer(&ammo_number);
	arc.ReadSafePointer(&weapon_icon);

	arc.ReadVector(&spawnspot);
	arc.ReadVector(&spawnangles);
	respawntimer = arc.ReadFloat();
	damagetimer = arc.ReadFloat();
	getontimer = arc.ReadFloat();

	bobsin = arc.ReadFloat();
	bobfrac = arc.ReadFloat();

	arc.ReadSafePointer(&oldweapon);
	rockets = arc.ReadInteger();
	bullets = arc.ReadInteger();
	mines = arc.ReadInteger();

	forwardmove = arc.ReadFloat();
	sidemove = arc.ReadFloat();
	upmove = arc.ReadFloat();

	arc.ReadVector(&move_angles);
	airpitch_timmer = arc.ReadFloat();
	speed = arc.ReadFloat();
	forward_speed = arc.ReadInteger();
	strafingroll = arc.ReadFloat();
	boosttimmer = arc.ReadFloat();
	turbo = arc.ReadFloat();

	weaponmode = arc.ReadInteger();

	sndflags = arc.ReadInteger();
	arc.ReadString(&currsound);

	effectstimmer = arc.ReadFloat();
	soundtimmer = arc.ReadFloat();
}

/*template class SafePtr<Hoverbike>;*/
typedef SafePtr<Hoverbike> HoverbikePtr;

extern int SV_Physics_Hoverbike(Hoverbike *bike);
extern int G_Physics_Hoverbike(Hoverbike *bike);

#endif /* hoverbike.h */
