#ifndef NETWORK_H_
#define NETWORK_H_

#include "Game.h"
#include "common.h"

#include "enet/enet.h"
#include "yaml-cpp/yaml.h"

#include <string>

namespace gln {

#define EMIT_DEFINE(msg) YAML::Emitter& operator <<(YAML::Emitter& out, const msg& m);

#define MESSAGE_PLAYER_SPAWN 0
#define MESSAGE_PLAYER_KILL 1
#define MESSAGE_ACCEPT 2
#define MESSAGE_PLAYER_UPDATE 3
#define MESSAGE_PLAYER_ACCELERATE 4
#define MESSAGE_BOMB_DROP 5
#define MESSAGE_BOMB_UPDATE 6
#define MESSAGE_POINT_UPDATE 7
#define MESSAGE_TEAM_UPDATE 8

struct player_spawn_message_t {
	enum {
		id = 0
	};
	size_t team_id;
	size_t player_id;
};
EMIT_DEFINE(player_spawn_message_t)

struct player_kill_message_t {
	enum {
		id = 1
	};
	uint16_t player_id;
};
EMIT_DEFINE(player_kill_message_t)

struct accept_message_t {
	enum {
		id = 2
	};
	uint16_t player_id;
};
EMIT_DEFINE(accept_message_t)

struct player_update_message_t {
	enum {
		id = 3
	};
	uint16_t player_id;
	//	unsigned int session;
	double x, y, z;
	double vx, vy, vz;
	uint16_t points;
};
EMIT_DEFINE(player_update_message_t)

struct player_accelerate_message_t {
	enum {
		id = 4
	};
	uint16_t player_id;
	double x, y, z;
	double rx, ry, rz;
};
EMIT_DEFINE(player_accelerate_message_t)

struct bomb_drop_meesage_t {
	enum {
		id = 5
	};
	double x, y, z;
	double vx, vy, vz;
	double ttl;
};
EMIT_DEFINE(bomb_drop_meesage_t)

struct bomb_update_meesage_t {
	enum {
		id = 5
	};
	uint16_t bomb_index;
	double x, y, z;
	double vx, vy, vz;
	double ttl;
};
EMIT_DEFINE(bomb_update_meesage_t)

struct point_update_mesage_t {
	enum {
		id = 7
	};
	uint16_t point_index;
	uint8_t status;
	double x, y, z;
};
EMIT_DEFINE(point_update_mesage_t)

struct team_update_message_t {
	enum {
		id = 8
	};
	uint16_t team_id;
	uint16_t points;
	uint16_t wins;
};
EMIT_DEFINE(team_update_message_t)

class Network {
public:
	Network(Game* game);
	void initialize(const std::string &host);
	void shutdown();
	void dispatch(uint8_t *data, size_t length);
	void service(uint32_t timeout);
	void sendGameUpdates();
	void sendMessage(uint8_t *data, size_t length);
	void send(const YAML::Emitter &em);
protected:
	Game *game;
	ENetHost *host;
	ENetPeer *client_peer;
};

} // namespace gln

#endif /* NETWORK_H_ */
