#ifndef POLYGUN_NETWORK_NETWORK_PACKET_HPP
#define POLYGUN_NETWORK_NETWORK_PACKET_HPP

#include <vector>
#include <cstdint>
#include <cstddef>

namespace polygun::network {
	enum NetworkPacketFlag {
		FLAG_NONE = 0b00000000,
		FLAG_RELIABLE = 0b10000000
	};

	// packets that are only sent to server are prefixed with PACKET_TO_SERVER_
	// same applies to client
	// packets with PACKET_ prefix apply to both
	enum NetworkPacketID {
		// join packets
		PACKET_HANDSHAKE = 0,
		// gameplay packets
		PACKET_ACTION,
		PACKET_MESSAGE,
		PACKET_TO_SERVER_CHUNK_REQUEST,
		// quit packets
		PACKET_EXIT,
		// control packets (for internal use only)
		PACKET_ACK
	};

	class NetworkPacket final {
	public:
		NetworkPacket(uint8_t flags, uint8_t id, uint32_t num = 0);
		NetworkPacket();
		~NetworkPacket() = default;

		void write(uint8_t val);
		void write(uint16_t val);
		void write(uint32_t val);
		void write(float val);

		bool load(const uint8_t* data, size_t size);
		uint8_t read_uint8();
		uint16_t read_uint16();
		uint32_t read_uint32();
		float read_float();

		void reset_reading_offset();
		void reset();

		const std::vector<uint8_t>& get_data() const { return m_data; }
		uint8_t get_flags() const { return m_flags; }
		uint8_t get_id() const { return m_id; }
		uint32_t get_num() const { return m_num; }

	private:
		uint8_t m_flags, m_id, m_num;
		size_t m_reading_offset;
		std::vector<uint8_t> m_data;
	};
}

#endif // POLYGUN_NETWORK_NETWORK_PACKET_HPP
