#ifndef PACKET_H
#define PACKET_H

#include "utils/Buffer.h"
#include "utils/StringBuffer.h"
#include "utils/Types.h"

enum class PacketType { RELIABLE, SEQUENCED, UNSEQUENCED };

class InPacket {
    const char* data;
    int size;
    int index;

public:
    InPacket(const void* data, int size);

    bool readU8(uint8& u);
    bool readU16(uint16& u);
    bool readU32(uint32& u);
    bool readS8(int8& s);
    bool readS16(int16& s);
    bool readS32(int32& s);
    bool readFloat(float& f);

    template<int N>
    bool readString(StringBuffer<N>& s) {
        uint16 end;
        if(readU16(end)) {
            return true;
        }
        s.clear();
        for(unsigned int i = 0; i < end; i++) {
            int8 c;
            if(readS8(c)) {
                return true;
            }
            s.append(c);
        }
        return false;
    }

private:
    bool read(void* buffer, int length);
};

struct OutPacket {
    Buffer buffer;

    OutPacket(int initialSize);

    OutPacket& writeU8(uint8 u);
    OutPacket& writeU16(uint16 u);
    OutPacket& writeU32(uint32 u);
    OutPacket& writeS8(int8 s);
    OutPacket& writeS16(int16 s);
    OutPacket& writeS32(int32 s);
    OutPacket& writeFloat(float f);

    template<int N>
    OutPacket& writeString(const StringBuffer<N>& s) {
        uint16 end = s.getLength() > 65535 ? 65535 : s.getLength();
        writeU16(end);
        for(unsigned int i = 0; i < end; i++) {
            writeS8(s[i]);
        }
        return *this;
    }
};

#endif