#include "xr_packet.h"

using namespace xray_re;

void xr_packet::r_raw(void* dest, size_t size)
{
	xr_assert(m_r_pos + size <= sizeof(m_buf));
	memmove(dest, m_buf + m_r_pos, size);
	m_r_pos += size;
}

void xr_packet::w_raw(const void* data, size_t size)
{
	assert(m_w_pos + size <= sizeof(m_buf));
	memmove(m_buf + m_w_pos, data, size);
	m_w_pos += size;
}

void xr_packet::r_begin(uint16_t& id)
{
	m_r_pos = 0;
	r_u16(id);
}

void xr_packet::w_begin(uint16_t id)
{
	m_w_pos = 0;
	w_u16(id);
}

const char* xr_packet::skip_sz()
{
	const char* p = reinterpret_cast<const char*>(m_buf + m_r_pos);
	while (m_r_pos < sizeof(m_buf)) {
		if (m_buf[m_r_pos++] == 0)
			return p;
	}
	// crash in debug mode if no 0 in the packet
	xr_assert(m_r_pos < sizeof(m_buf));
	return p;
}

void xr_packet::r_sz(std::string& value)
{
	uint8_t* p = &m_buf[m_r_pos];
	while (m_r_pos < sizeof(m_buf)) {
		if (m_buf[m_r_pos++] == 0) {
			value.assign(p, &m_buf[m_r_pos - 1]);
			return;
		}
	}
	// crash in debug mode if no 0 in the packet
	assert(m_r_pos < sizeof(m_buf));
	value.assign(p, m_buf + m_r_pos);
}

float xr_packet::r_angle8()
{
	r_u8();
	return 0;
}

void xr_packet::r_dir(fvector3& value)
{
	value.decompress(r_u16());
}

void xr_packet::r_sdir(fvector3& value)
{
	value.decompress(r_u16());
	value.mul(r_float());
}

void xr_packet::w_sdir(const fvector3& value)
{
	fvector3 temp;
	float m = value.square_magnitude();
	if (m < 1e-7f) {
		temp.set(0, 0, 0);
		m = 0;
	} else {
		temp.mul(value, 1.f/m);
	}
	w_u16(temp.compress());
	w_float(m);
}

void xr_packet::w_sz(const std::string& value)
{
	w_raw(value.data(), value.length() + 1);
}

void xr_packet::r_matrix(fmatrix& value)
{
	r_vec3(value.i); value._14 = 0;
	r_vec3(value.j); value._24 = 0;
	r_vec3(value.k); value._34 = 0;
	r_vec3(value.c); value._44 = 1.f;
}

void xr_packet::w_matrix(const fmatrix& value)
{
	w_vec3(value.i);
	w_vec3(value.j);
	w_vec3(value.k);
	w_vec3(value.c);
}

void xr_packet::init(const uint8_t* data, size_t size)
{
	xr_assert(size < sizeof(m_buf));
	m_r_pos = m_w_pos = 0;
//	m_r_pos = 0;
//	m_w_pos = size;
	memmove(m_buf, data, size);
}
