// connection.h: Beispielspieler für Asteroids (Verbindung zu Mame)
// Harald Bögeholz / c't; Umstrukturierung Matthias Fuchs

#ifndef ConnectionH
#define ConnectionH

#include <stdio.h>

#if defined(WINDOWS) || defined(_WIN32)
#include <winsock2.h>
#define ADDRESS DWORD
#else
#define SOCKET int
#define ADDRESS in_addr_t
// 3 Includes für sockaddr_in
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif


#pragma pack(1)
// byteweise Ausrichtung der Datenstrukturen
struct FramePacket
{
	unsigned __int8 vectorram[1024];
	__int8 frameno;  // wird bei jedem Frame inkrementiert
	__int8 ping;	  // Der Server schickt das letzte empfangene ping-Byte zurück

	FramePacket(void);
};

class KeysPacket
{
private:
	static const char KEY_HYPERSPACE = 1;
	static const char KEY_FIRE = 2;
	static const char KEY_THRUST = 4;
	static const char KEY_RIGHT = 8;
	static const char KEY_LEFT = 0x10;
	static const char KEY_START = 0x20;

	char signature[6];
	char keys;
public:
	__int8 ping;	  // wird vom Server bei nächster Gelegenheit zurückgeschickt. Für Latenzmessung.

	KeysPacket(void);
	void clear(void);			 // alle Tasten loslassen
	void start(bool b);		  // Startbutton drücken (true) oder loslassen (false)
										// (nur mit aktualisierter Mame)
	void hyperspace(bool b);	// Hyperspace drücken (true) oder loslassen (false)
	void fire(bool b);			// Feuerknopf drücken (true) oder loslassen (false)
	void thrust(bool b);		 // Beschleunigen ...
	void right(bool b);		  // rechts drehen ...
	void left(bool b);			// links drehen

	bool start(void) const;
	bool hyperspace(void) const;
	bool fire(void) const;
	bool thrust(void) const;
	bool right(void) const;
	bool left(void) const;
};
#pragma pack()


class connection_error
{
public:
	connection_error (const char* format, ...);
	inline const char* what(void) const;
private:
	char message[1024];
};


class Connection
{
public:
	Connection (const char* server_ip_str);
	~Connection();
	void ReceivePacket(FramePacket &packet);
	void SendPacket(const KeysPacket &packet);
	static bool IsLittleEndian(void);
private:
	SOCKET sd;
	ADDRESS server_ip;
};



inline const char* connection_error::what(void) const
{
	return message;
}

#endif
