#include "m3dm.h"
#include "file.h"
#include "m3derror.h"
#include <string.h>
#include <errno.h>

namespace M3D
{

M3DM::M3DM() : _header_ (0)
{}


M3DM::~M3DM()
{}

void M3DM::load( std::string fname )
{
	//Отобразим файл в память
	_mapped_file_.mmap ( fname.c_str() );
	char *mapped_file_pointer = _mapped_file_.get_pointer();
	
	_header_ = (M3DM_Header*)mapped_file_pointer;
	_data_.model_name = mapped_file_pointer + _header_->model_name_offset;
	_data_.base_path = mapped_file_pointer + _header_->base_path_offset;
	_data_.material_name = mapped_file_pointer + _header_->material_name_offset;
	_data_.mesh_name = mapped_file_pointer + _header_->mesh_name_offset;
}

void M3DM::save( std::string fname )
{
	File fdesc ( fname.c_str(), true );
	//Скорректируем заголовок
	int base_offset = sizeof(M3DM_Header);
	_header_->base_path_offset = base_offset;
	_header_->model_name_offset = _header_->base_path_offset + _header_->base_path_length;
	_header_->material_name_offset = _header_->model_name_offset + _header_->model_name_length;
	_header_->mesh_name_offset = _header_->material_name_offset + _header_->material_name_length;
	 
	//Сохраним заголовок
	if(write(fdesc, _header_, sizeof(M3DM_Header)) != sizeof(M3DM_Header))THROW ( strerror ( errno ) );
	//Сохраним данные
	if(write(fdesc, _data_.base_path, _header_->base_path_length) != _header_->base_path_length)
		THROW ( strerror ( errno ) );
	if(write(fdesc, _data_.model_name, _header_->model_name_length) != _header_->model_name_length)
		THROW ( strerror ( errno ) );
	if(write(fdesc, _data_.material_name, _header_->material_name_length) != _header_->material_name_length)
		THROW ( strerror ( errno ) );
	if(write(fdesc, _data_.mesh_name, _header_->mesh_name_length) != _header_->mesh_name_length)
		THROW ( strerror ( errno ) );
}

void M3DM::set_header( M3DM_Header * value )
{
	_header_ = value;
	memcpy(_header_->signature, M3DM_SIGNATURE, strlen(M3DM_SIGNATURE));
	_header_->version = M3DM_VER_MAGIC;
}

void M3DM::set_data( M3DM_Data * value )
{
	_data_ = *value;
}

}
