#include "types.h"
#include "common.h"

// BookHandle xlCreateBook(void);
ERL_NIF_TERM c_xlCreateBook(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookHandle book_handle = xlCreateBook();

	if(!book_handle) {
		return enif_make_atom(env, "nil");
	} else {
		BookType *resource = enif_alloc_resource(TypeOfBook, sizeof(BookType));

		resource->handle = book_handle;

		ERL_NIF_TERM resource_handle = enif_make_resource(env, resource);

		enif_release_resource(resource);

		return resource_handle;
	}
}

// BookHandle xlCreateXMLBook(void);
ERL_NIF_TERM c_xlCreateXMLBook(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookHandle book_handle = xlCreateXMLBook();

	if(!book_handle) {
		return enif_make_atom(env, "nil");
	} else {
		BookType *resource = enif_alloc_resource(TypeOfBook, sizeof(BookType));

		resource->handle = book_handle;

		ERL_NIF_TERM resource_handle = enif_make_resource(env, resource);

		enif_release_resource(resource);

		return resource_handle;
	}
}

// int xlBookLoad(BookHandle handle, const wchar_t* filename);
ERL_NIF_TERM c_xlBookLoad(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	ErlNifBinary filename_temp;

	if(0 == enif_inspect_binary(env, argv[1], &filename_temp)) {
		return enif_make_badarg(env);
	}

	unsigned char *pt = createNullTermMbString(filename_temp);

	if(!pt) {
		return enif_make_badarg(env);
	}

	size_t mbs_len = strlen((const char*)pt);

	size_t character_count = mbstowcs(NULL, (const char*)pt, mbs_len);

	wchar_t w_filename[character_count + 1];

	(void)memset(w_filename, '\0', sizeof(w_filename) / sizeof(w_filename[0]));

	if((size_t)-1 == mbstowcs(w_filename, (const char*)pt, character_count + 1)) {
		free(pt);

		return enif_make_badarg(env);
	}

	free(pt);

	int ret = xlBookLoad(resource->handle, w_filename);

	return enif_make_int(env, ret);
}

// int xlBookSave(BookHandle handle, const wchar_t* filename);
ERL_NIF_TERM c_xlBookSave(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	ErlNifBinary filename_temp;

	if(enif_inspect_binary(env, argv[1], &filename_temp) < 1) {
		return enif_make_badarg(env);
	}

	unsigned char *pt = createNullTermMbString(filename_temp);

	if(!pt) {
		return enif_make_badarg(env);
	}

	size_t mbs_len = strlen((const char*)pt);

	size_t character_count = mbstowcs(NULL, (const char*)pt, mbs_len);

	wchar_t w_filename[character_count + 1];

	(void)memset(w_filename, '\0', sizeof(w_filename) / sizeof(w_filename[0]));

	if((size_t)-1 == mbstowcs(w_filename, (const char*)pt, character_count + 1)) {
		free(pt);

		return enif_make_badarg(env);
	}

	free(pt);

	int ret = xlBookSave(resource->handle, w_filename);

	return enif_make_int(env, ret);
}

// int xlBookLoadUsingTempFile(BookHandle handle, const wchar_t* filename, const wchar_t* tempFile);
ERL_NIF_TERM c_xlBookLoadUsingTempFile(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	ErlNifBinary filename_temp;

	if(enif_inspect_binary(env, argv[1], &filename_temp) < 1) {
		return enif_make_badarg(env);
	}

	unsigned char *pt1 = createNullTermMbString(filename_temp);

	if(!pt1) {
		return enif_make_badarg(env);
	}

	size_t mbs_len1 = strlen((const char*)pt1);

	size_t character_count1 = mbstowcs(NULL, (const char*)pt1, mbs_len1);

	wchar_t w_filename[character_count1 + 1];

	(void)memset(w_filename, '\0', sizeof(w_filename) / sizeof(w_filename[0]));

	if((size_t)-1 == mbstowcs(w_filename, (const char*)pt1, character_count1 + 1)) {
		free(pt1);

		return enif_make_badarg(env);
	}

	free(pt1);

	ErlNifBinary tempfile_temp;

	if(enif_inspect_binary(env, argv[1], &tempfile_temp) < 1) {
		return enif_make_badarg(env);
	}

	unsigned char *pt2 = createNullTermMbString(tempfile_temp);

	if(!pt2) {
		return enif_make_badarg(env);
	}

	size_t mbs_len2 = strlen((const char*)pt2);

	size_t character_count2 = mbstowcs(NULL, (const char*)pt2, mbs_len2);

	wchar_t w_tempfile[character_count2 + 1];

	(void)memset(w_tempfile, '\0', sizeof(w_tempfile) / sizeof(w_tempfile[0]));

	if((size_t)-1 == mbstowcs(w_tempfile, (const char*)pt2, character_count2 + 1)) {
		free(pt2);

		return enif_make_badarg(env);
	}

	free(pt2);

	int ret = xlBookLoadUsingTempFile(resource->handle, w_filename, w_tempfile);

	return enif_make_int(env, ret);
}

// int xlBookSaveUsingTempFile(BookHandle handle, const wchar_t* filename, int useTempFile);
ERL_NIF_TERM c_xlBookSaveUsingTempFile(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	ErlNifBinary filename_temp;

	if(enif_inspect_binary(env, argv[1], &filename_temp) < 1) {
		return enif_make_badarg(env);
	}

	unsigned char *pt = createNullTermMbString(filename_temp);

	if(!pt) {
		return enif_make_badarg(env);
	}

	size_t mbs_len = strlen((const char*)pt);

	size_t character_count = mbstowcs(NULL, (const char*)pt, mbs_len);

	wchar_t w_filename[character_count + 1];

	(void)memset(w_filename, '\0', sizeof(w_filename) / sizeof(w_filename[0]));

	if((size_t)-1 == mbstowcs(w_filename, (const char*)pt, character_count + 1)) {
		free(pt);

		return enif_make_badarg(env);
	}

	free(pt);

	int use_temp_file;

	if (0 == enif_get_int(env, argv[2], &use_temp_file)) {
		return enif_make_badarg(env);
	}

	int ret = xlBookSaveUsingTempFile(resource->handle, w_filename, use_temp_file);

	return enif_make_int(env, ret);
}

// int xlBookLoadPartially(BookHandle handle, const wchar_t* filename, int sheetIndex, int firstRow, int lastRow);
ERL_NIF_TERM c_xlBookLoadPartially(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	ErlNifBinary filename_temp;

	if(enif_inspect_binary(env, argv[1], &filename_temp) < 1) {
		return enif_make_badarg(env);
	}

	unsigned char *pt = createNullTermMbString(filename_temp);

	if(!pt) {
		return enif_make_badarg(env);
	}

	size_t mbs_len = strlen((const char*)pt);

	size_t character_count = mbstowcs(NULL, (const char*)pt, mbs_len);

	wchar_t w_filename[character_count + 1];

	(void)memset(w_filename, '\0', sizeof(w_filename) / sizeof(w_filename[0]));

	if((size_t)-1 == mbstowcs(w_filename, (const char*)pt, character_count + 1)) {
		free(pt);

		return enif_make_badarg(env);
	}

	free(pt);

	int sheet_index;

	if (0 == enif_get_int(env, argv[2], &sheet_index)) {
		return enif_make_badarg(env);
	}

	int first_row;

	if (0 == enif_get_int(env, argv[3], &first_row)) {
		return enif_make_badarg(env);
	}

	int last_row;

	if (0 == enif_get_int(env, argv[4], &last_row)) {
		return enif_make_badarg(env);
	}

	int ret = xlBookLoadPartially(resource->handle, w_filename, sheet_index, first_row, last_row);

	return enif_make_int(env, ret);
}

// int xlBookLoadPartiallyUsingTempFile(BookHandle handle, const wchar_t* filename, int sheetIndex, int firstRow, int lastRow, const wchar_t* tempFile);
ERL_NIF_TERM c_xlBookLoadPartiallyUsingTempFile(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	ErlNifBinary filename_temp;

	if(enif_inspect_binary(env, argv[1], &filename_temp) < 1) {
		return enif_make_badarg(env);
	}

	unsigned char *pt1 = createNullTermMbString(filename_temp);

	if(!pt1) {
		return enif_make_badarg(env);
	}

	size_t mbs_len1 = strlen((const char*)pt1);

	size_t character_count1 = mbstowcs(NULL, (const char*)pt1, mbs_len1);

	wchar_t w_filename[character_count1 + 1];

	(void)memset(w_filename, '\0', sizeof(w_filename) / sizeof(w_filename[0]));

	if((size_t)-1 == mbstowcs(w_filename, (const char*)pt1, character_count1 + 1)) {
		free(pt1);

		return enif_make_badarg(env);
	}

	free(pt1);

	int sheet_index;

	if (0 == enif_get_int(env, argv[2], &sheet_index)) {
		return enif_make_badarg(env);
	}

	int first_row;

	if (0 == enif_get_int(env, argv[3], &first_row)) {
		return enif_make_badarg(env);
	}

	int last_row;

	if (0 == enif_get_int(env, argv[4], &last_row)) {
		return enif_make_badarg(env);
	}

	ErlNifBinary tempfile_temp;

	if(enif_inspect_binary(env, argv[5], &tempfile_temp) < 1) {
		return enif_make_badarg(env);
	}

	unsigned char *pt2 = createNullTermMbString(tempfile_temp);

	if(!pt2) {
		return enif_make_badarg(env);
	}

	size_t mbs_len2 = strlen((const char*)pt2);

	size_t character_count2 = mbstowcs(NULL, (const char*)pt2, mbs_len2);

	wchar_t w_tempfile[character_count2 + 1];

	(void)memset(w_tempfile, '\0', sizeof(w_tempfile) / sizeof(w_tempfile[0]));

	if((size_t)-1 == mbstowcs(w_tempfile, (const char*)pt2, character_count2 + 1)) {
		free(pt2);

		return enif_make_badarg(env);
	}

	free(pt2);

	int ret = xlBookLoadPartiallyUsingTempFile(resource->handle, w_filename, sheet_index, first_row, last_row, w_tempfile);

	return enif_make_int(env, ret);
}

// int xlBookLoadWithoutEmptyCells(BookHandle handle, const wchar_t* filename);
ERL_NIF_TERM c_xlBookLoadWithoutEmptyCells(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	ErlNifBinary filename_temp;

	if(enif_inspect_binary(env, argv[1], &filename_temp) < 1) {
		return enif_make_badarg(env);
	}

	unsigned char *pt = createNullTermMbString(filename_temp);

	if(!pt) {
		return enif_make_badarg(env);
	}

	size_t mbs_len = strlen((const char*)pt);

	size_t character_count = mbstowcs(NULL, (const char*)pt, mbs_len);

	wchar_t w_filename[character_count + 1];

	(void)memset(w_filename, '\0', sizeof(w_filename) / sizeof(w_filename[0]));

	if((size_t)-1 == mbstowcs(w_filename, (const char*)pt, character_count + 1)) {
		free(pt);

		return enif_make_badarg(env);
	}

	free(pt);

	int ret = xlBookLoadWithoutEmptyCells(resource->handle, w_filename);

	return enif_make_int(env, ret);
}

// int xlBookLoadInfo(BookHandle handle, const wchar_t* filename);
ERL_NIF_TERM c_xlBookLoadInfo(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	ErlNifBinary filename_temp;

	if(enif_inspect_binary(env, argv[1], &filename_temp) < 1) {
		return enif_make_badarg(env);
	}

	unsigned char *pt = createNullTermMbString(filename_temp);

	if(!pt) {
		return enif_make_badarg(env);
	}

	size_t mbs_len = strlen((const char*)pt);

	size_t character_count = mbstowcs(NULL, (const char*)pt, mbs_len);

	wchar_t w_filename[character_count + 1];

	(void)memset(w_filename, '\0', sizeof(w_filename) / sizeof(w_filename[0]));

	if((size_t)-1 == mbstowcs(w_filename, (const char*)pt, character_count + 1)) {
		free(pt);

		return enif_make_badarg(env);
	}

	free(pt);

	int ret = xlBookLoadInfo(resource->handle, w_filename);

	return enif_make_int(env, ret);
}

// int xlBookLoadRaw(BookHandle handle, const char* data, unsigned size);
ERL_NIF_TERM c_xlBookLoadRaw(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	ErlNifBinary data;

	if(enif_inspect_binary(env, argv[1], &data) < 1) {
		return enif_make_badarg(env);
	}

	unsigned size;

	if (0 == enif_get_uint(env, argv[2], &size)) {
		return enif_make_badarg(env);
	}

	int ret = xlBookLoadRaw(resource->handle, (const char*)data.data, size);

	return enif_make_int(env, ret);
}

// int xlBookLoadRawPartially(BookHandle handle, const char* data, unsigned size, int sheetIndex, int firstRow, int lastRow);
ERL_NIF_TERM c_xlBookLoadRawPartially(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	ErlNifBinary data;

	if(enif_inspect_binary(env, argv[1], &data) < 1) {
		return enif_make_badarg(env);
	}

	unsigned size;

	if (0 == enif_get_uint(env, argv[2], &size)) {
		return enif_make_badarg(env);
	}

	int sheet_index;

	if (0 == enif_get_int(env, argv[3], &sheet_index)) {
		return enif_make_badarg(env);
	}

	int first_row;

	if (0 == enif_get_int(env, argv[4], &first_row)) {
		return enif_make_badarg(env);
	}

	int last_row;

	if (0 == enif_get_int(env, argv[5], &last_row)) {
		return enif_make_badarg(env);
	}

	int ret = xlBookLoadRawPartially(resource->handle, (const char*)data.data, size, sheet_index, first_row, last_row);

	return enif_make_int(env, ret);
}

// int xlBookSaveRaw(BookHandle handle, const char** data, unsigned* size);
ERL_NIF_TERM c_xlBookSaveRaw(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	const char *data;

	unsigned size = 0;

	int ret = xlBookSaveRaw(resource->handle, &data, &size);

	ErlNifBinary data_binary;

	if(data && ret != 0) {
		enif_alloc_binary(size, &data_binary);

		memcpy(data_binary.data, data, size);

		data_binary.size = size;
	}

	return enif_make_list3(env,
		enif_make_int(env, ret),
		enif_make_binary(env, &data_binary),
		enif_make_int(env, size)
	);
}

// SheetHandle xlBookAddSheet(BookHandle handle, const wchar_t* name, SheetHandle initSheet);
ERL_NIF_TERM c_xlBookAddSheet(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	ErlNifBinary name_temp;

	if(enif_inspect_binary(env, argv[1], &name_temp) < 1) {
		return enif_make_badarg(env);
	}

	unsigned char *pt = createNullTermMbString(name_temp);

	if(!pt) {
		return enif_make_badarg(env);
	}

	size_t mbs_len = strlen((const char*)pt);

	size_t character_count = mbstowcs(NULL, (const char*)pt, mbs_len);

	wchar_t w_name[character_count + 1];

	(void)memset(w_name, '\0', sizeof(w_name) / sizeof(w_name[0]));

	if((size_t)-1 == mbstowcs(w_name, (const char*)pt, character_count + 1)) {
		free(pt);

		return enif_make_badarg(env);
	}

	free(pt);

	SheetType *init_sheet = NULL;

	SheetType tmp = {NULL};

	if(isNilAtom(env, argv[2])) {
		init_sheet = &tmp;
	} else {
		if (0 == enif_get_resource(env, argv[2], TypeOfSheet, (void**)&init_sheet)) {
			return enif_make_badarg(env);
		}
	}

	SheetHandle sheet_handle = xlBookAddSheet(resource->handle, w_name, init_sheet->handle);

	if(!sheet_handle) {
		return enif_make_atom(env, "nil");
	} else {
		SheetType *ret_resource = enif_alloc_resource(TypeOfSheet, sizeof(SheetType));

		ret_resource->handle = sheet_handle;

		ERL_NIF_TERM resource_handle = enif_make_resource(env, ret_resource);

		enif_release_resource(ret_resource);

		return resource_handle;
	}
}

// SheetHandle xlBookInsertSheet(BookHandle handle, int index, const wchar_t* name, SheetHandle initSheet);
ERL_NIF_TERM c_xlBookInsertSheet(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int index;

	if (0 == enif_get_int(env, argv[1], &index)) {
		return enif_make_badarg(env);
	}

	ErlNifBinary name_temp;

	if(enif_inspect_binary(env, argv[2], &name_temp) < 1) {
		return enif_make_badarg(env);
	}

	unsigned char *pt = createNullTermMbString(name_temp);

	if(!pt) {
		return enif_make_badarg(env);
	}

	size_t mbs_len = strlen((const char*)pt);

	size_t character_count = mbstowcs(NULL, (const char*)pt, mbs_len);

	wchar_t w_name[character_count + 1];

	(void)memset(w_name, '\0', sizeof(w_name) / sizeof(w_name[0]));

	if((size_t)-1 == mbstowcs(w_name, (const char*)pt, character_count + 1)) {
		free(pt);

		return enif_make_badarg(env);
	}

	free(pt);

	SheetType *init_sheet = NULL;

	SheetType tmp = {NULL};

	if(isNilAtom(env, argv[3])) {
		init_sheet = &tmp;
	} else {
		if (0 == enif_get_resource(env, argv[3], TypeOfSheet, (void**)&init_sheet)) {
			return enif_make_badarg(env);
		}
	}

	SheetHandle sheet_handle = xlBookInsertSheet(resource->handle, index, w_name, init_sheet->handle);

	if(!sheet_handle) {
		return enif_make_atom(env, "nil");
	} else {
		SheetType *ret_resource = enif_alloc_resource(TypeOfSheet, sizeof(SheetType));

		ret_resource->handle = sheet_handle;

		ERL_NIF_TERM resource_handle = enif_make_resource(env, ret_resource);

		enif_release_resource(ret_resource);

		return resource_handle;
	}
}

// SheetHandle xlBookGetSheet(BookHandle handle, int index);
ERL_NIF_TERM c_xlBookGetSheet(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int index;

	if (0 == enif_get_int(env, argv[1], &index)) {
		return enif_make_badarg(env);
	}

	SheetHandle sheet_handle = xlBookGetSheet(resource->handle, index);

	if(!sheet_handle) {
		return enif_make_atom(env, "nil");
 	} else {
		SheetType *ret_resource = enif_alloc_resource(TypeOfSheet, sizeof(SheetType));

		ret_resource->handle = sheet_handle;

		ERL_NIF_TERM resource_handle = enif_make_resource(env, ret_resource);

		enif_release_resource(ret_resource);

		return resource_handle;
	}
}

// wchar_t* xlBookGetSheetName(BookHandle handle, int index);
ERL_NIF_TERM c_xlBookGetSheetName(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int index;

	if (0 == enif_get_int(env, argv[1], &index)) {
		return enif_make_badarg(env);
	}

	const wchar_t *p = xlBookGetSheetName(resource->handle, index);

	char mes[128];

	(void)memset(mes, '\0', 128);

	if(-1 == wcstombs(mes, p, 128)) {
		return enif_make_badarg(env);
	}

	ErlNifBinary ret;

	enif_alloc_binary(strlen(mes), &ret);

	strcpy((char*)ret.data, mes);

	return enif_make_binary(env, &ret);
}

// int xlBookSheetType(BookHandle handle, int index);
ERL_NIF_TERM c_xlBookSheetType(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int index;

	if (0 == enif_get_int(env, argv[1], &index)) {
		return enif_make_badarg(env);
	}

	int ret = xlBookSheetType(resource->handle, index);

	return enif_make_int(env, ret);
}

// int xlBookMoveSheet(BookHandle handle, int srcIndex, int dstIndex);
ERL_NIF_TERM c_xlBookMoveSheet(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int src_index;

	if (0 == enif_get_int(env, argv[1], &src_index)) {
		return enif_make_badarg(env);
	}

	int dst_index;

	if (0 == enif_get_int(env, argv[2], &dst_index)) {
		return enif_make_badarg(env);
	}

	int ret = xlBookMoveSheet(resource->handle, src_index, dst_index);

	return enif_make_int(env, ret);
}

// int xlBookDelSheet(BookHandle handle, int index);
ERL_NIF_TERM c_xlBookDelSheet(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int index;

	if (0 == enif_get_int(env, argv[1], &index)) {
		return enif_make_badarg(env);
	}

	int ret = xlBookDelSheet(resource->handle, index);

	return enif_make_int(env, ret);
}

// int xlBookSheetCount(BookHandle handle);
ERL_NIF_TERM c_xlBookSheetCount(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int ret = xlBookSheetCount(resource->handle);

	return enif_make_int(env, ret);
}

// FormatHandle xlBookAddFormat(BookHandle handle, FormatHandle initFormat);
ERL_NIF_TERM c_xlBookAddFormat(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	FormatType *init_format = NULL;

	FormatType tmp = {NULL};

	if(isNilAtom(env, argv[1])) {
		init_format = &tmp;
	} else {
		if (0 == enif_get_resource(env, argv[1], TypeOfFormat, (void**)&init_format)) {
			return enif_make_badarg(env);
		}
	}

	FormatHandle format_handle = xlBookAddFormat(resource->handle, init_format->handle);

	if(!format_handle) {
		return enif_make_atom(env, "nil");
	} else {
		FormatType *ret_resource = enif_alloc_resource(TypeOfFormat, sizeof(FormatType));

		ret_resource->handle = format_handle;

		ERL_NIF_TERM resource_handle = enif_make_resource(env, ret_resource);

		enif_release_resource(ret_resource);

		return resource_handle;
	}
}

// FontHandle xlBookAddFont(BookHandle handle, FontHandle initFont);
ERL_NIF_TERM c_xlBookAddFont(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	FontType *init_font = NULL;

	FontType tmp = {NULL};

	if(isNilAtom(env, argv[1])) {
		init_font = &tmp;
	} else {
		if (0 == enif_get_resource(env, argv[1], TypeOfFont, (void**)&init_font)) {
			return enif_make_badarg(env);
		}
	}

	FontHandle font_handle = xlBookAddFont(resource->handle, init_font->handle);

	if(!font_handle) {
		return enif_make_atom(env, "nil");
	} else {
		FontType *ret_resource = enif_alloc_resource(TypeOfFont, sizeof(FontType));

		ret_resource->handle = font_handle;

		ERL_NIF_TERM resource_handle = enif_make_resource(env, ret_resource);

		enif_release_resource(ret_resource);

		return resource_handle;
	}
}

// RichStringHandle xlBookAddRichString(BookHandle handle);
ERL_NIF_TERM c_xlBookAddRichString(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	RichStringHandle rich_string_handle = xlBookAddRichString(resource->handle);

	if(!rich_string_handle) {
		return enif_make_atom(env, "nil");
	} else {
		RichStringType *ret_resource = enif_alloc_resource(TypeOfRichString, sizeof(RichStringType));

		ret_resource->handle = rich_string_handle;

		ERL_NIF_TERM resource_handle = enif_make_resource(env, ret_resource);

		enif_release_resource(ret_resource);

		return resource_handle;
	}
}

// int xlBookAddCustomNumFormat(BookHandle handle, const wchar_t* customNumFormat);
ERL_NIF_TERM c_xlBookAddCustomNumFormat(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	ErlNifBinary custom_num_format_temp;

	if(enif_inspect_binary(env, argv[1], &custom_num_format_temp) < 1) {
		return enif_make_badarg(env);
	}

	unsigned char *pt = createNullTermMbString(custom_num_format_temp);

	if(!pt) {
		return enif_make_badarg(env);
	}

	size_t mbs_len = strlen((const char*)pt);

	size_t character_count = mbstowcs(NULL, (const char*)pt, mbs_len);

	wchar_t w_custom_num_format[character_count + 1];

	(void)memset(w_custom_num_format, '\0', sizeof(w_custom_num_format) / sizeof(w_custom_num_format[0]));

	if((size_t)-1 == mbstowcs(w_custom_num_format, (const char*)pt, character_count + 1)) {
		free(pt);

		return enif_make_badarg(env);
	}

	free(pt);

	int ret = xlBookAddCustomNumFormat(resource->handle, w_custom_num_format);

	return enif_make_int(env, ret);
}

// wchar_t* xlBookCustomNumFormat(BookHandle handle, int fmt);
ERL_NIF_TERM c_xlBookCustomNumFormat(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int fmt;

	if (0 == enif_get_int(env, argv[1], &fmt)) {
		return enif_make_badarg(env);
	}

	const wchar_t *wstr = xlBookCustomNumFormat(resource->handle, fmt);

	if(!wstr) {
		return enif_make_atom(env, "nil");
	}

	ErlNifBinary ret = convertWcharToMbBinary(wstr);

	if(!ret.data) {
		return enif_make_atom(env, "error");
	}

	return enif_make_binary(env, &ret);
}

// FormatHandle xlBookFormat(BookHandle handle, int index);
ERL_NIF_TERM c_xlBookFormat(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int index;

	if (0 == enif_get_int(env, argv[1], &index)) {
		return enif_make_badarg(env);
	}

	FormatHandle format_handle = xlBookFormat(resource->handle, index);

	if(!format_handle) {
		return enif_make_atom(env, "nil");
	} else {
		FormatType *ret_resource = enif_alloc_resource(TypeOfFormat, sizeof(FormatType));

		ret_resource->handle = format_handle;

		ERL_NIF_TERM resource_handle = enif_make_resource(env, ret_resource);

		enif_release_resource(ret_resource);

		return resource_handle;
	}
}

// int xlBookFormatSize(BookHandle handle);
ERL_NIF_TERM c_xlBookFormatSize(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int ret = xlBookFormatSize(resource->handle);

	return enif_make_int(env, ret);
}

// FontHandle xlBookFont(BookHandle handle, int index);
ERL_NIF_TERM c_xlBookFont(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int index;

	if (0 == enif_get_int(env, argv[1], &index)) {
		return enif_make_badarg(env);
	}

	FontHandle font_handle = xlBookFont(resource->handle, index);

	if(!font_handle) {
		return enif_make_atom(env, "nil");
	} else {
		FontType *ret_resource = enif_alloc_resource(TypeOfFont, sizeof(FontType));

		ret_resource->handle = font_handle;

		ERL_NIF_TERM resource_handle = enif_make_resource(env, ret_resource);

		enif_release_resource(ret_resource);

		return resource_handle;
	}
}

// int xlBookFontSize(BookHandle handle);
ERL_NIF_TERM c_xlBookFontSize(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int ret = xlBookFontSize(resource->handle);

	return enif_make_int(env, ret);
}

// double xlBookDatePack(BookHandle handle, int year, int month, int day, int hour, int min, int sec, int msec);
ERL_NIF_TERM c_xlBookDatePack(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int year;

	if (0 == enif_get_int(env, argv[1], &year)) {
		return enif_make_badarg(env);
	}

	int month;

	if (0 == enif_get_int(env, argv[2], &month)) {
		return enif_make_badarg(env);
	}

	int day;

	if (0 == enif_get_int(env, argv[3], &day)) {
		return enif_make_badarg(env);
	}

	int hour;

	if (0 == enif_get_int(env, argv[4], &hour)) {
		return enif_make_badarg(env);
	}

	int min;

	if (0 == enif_get_int(env, argv[5], &min)) {
		return enif_make_badarg(env);
	}

	int sec;

	if (0 == enif_get_int(env, argv[6], &sec)) {
		return enif_make_badarg(env);
	}

	int msec;

	if (0 == enif_get_int(env, argv[7], &msec)) {
		return enif_make_badarg(env);
	}

	double ret = xlBookDatePack(resource->handle, year, month, day, hour, min, sec, msec);

	return enif_make_double(env, ret);
}

// int xlBookDateUnpack(BookHandle handle, double value, int* year, int* month, int* day, int* hour, int* min, int* sec, int* msec);
ERL_NIF_TERM c_xlBookDateUnpack(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	double value;

	if (0 == enif_get_double(env, argv[1], &value)) {
		return enif_make_badarg(env);
	}

	int year;

	int month;

	int day;

	int hour;

	int min;

	int sec;

	int msec;

	int ret = xlBookDateUnpack(resource->handle, value, &year, &month, &day, &hour, &min, &sec, &msec);

	return enif_make_list8(env,
		enif_make_int(env, ret),
		enif_make_int(env, year),
		enif_make_int(env, month),
		enif_make_int(env, day),
		enif_make_int(env, hour),
		enif_make_int(env, min),
		enif_make_int(env, sec),
		enif_make_int(env, msec)
	);
}

// int xlBookColorPack(BookHandle handle, int red, int green, int blue);
ERL_NIF_TERM c_xlBookColorPack(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int red;

	if (0 == enif_get_int(env, argv[1], &red)) {
		return enif_make_badarg(env);
	}

	int green;

	if (0 == enif_get_int(env, argv[2], &green)) {
		return enif_make_badarg(env);
	}

	int blue;

	if (0 == enif_get_int(env, argv[3], &blue)) {
		return enif_make_badarg(env);
	}

	int ret = xlBookColorPack(resource->handle, red, green, blue);

	return enif_make_int(env, ret);
}

// void xlBookColorUnpack(BookHandle handle, int color, int* red, int* green, int* blue);
ERL_NIF_TERM c_xlBookColorUnpack(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int color;

	if (0 == enif_get_int(env, argv[1], &color)) {
		return enif_make_badarg(env);
	}

	int red;

	int green;

	int blue;

	xlBookColorUnpack(resource->handle, color, &red, &green, &blue);

	return enif_make_list3(env,
		enif_make_int(env, red),
		enif_make_int(env, green),
		enif_make_int(env, blue)
	);
}

// int xlBookActiveSheet(BookHandle handle);
ERL_NIF_TERM c_xlBookActiveSheet(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int ret = xlBookActiveSheet(resource->handle);

	return enif_make_int(env, ret);
}

// void xlBookSetActiveSheet(BookHandle handle, int index);
ERL_NIF_TERM c_xlBookSetActiveSheet(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int index;

	if (0 == enif_get_int(env, argv[1], &index)) {
		return enif_make_badarg(env);
	}

	xlBookSetActiveSheet(resource->handle, index);

	return enif_make_atom(env, "nil");
}

// int xlBookPictureSize(BookHandle handle);
ERL_NIF_TERM c_xlBookPictureSize(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int ret = xlBookPictureSize(resource->handle);

	return enif_make_int(env, ret);
}

// int xlBookGetPicture(BookHandle handle, int index, const char** data, unsigned* size);
ERL_NIF_TERM c_xlBookGetPicture(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int index;

	if (0 == enif_get_int(env, argv[1], &index)) {
		return enif_make_badarg(env);
	}

	const char *data;

	unsigned size;

	int ret = xlBookGetPicture(resource->handle, index, &data, &size);

	ErlNifBinary data_binary;

	if(data) {
		enif_alloc_binary(size, &data_binary);

		memcpy(data_binary.data, data, size);

		data_binary.size = size;
	}

	return enif_make_list3(env,
		enif_make_int(env, ret),
		enif_make_binary(env, &data_binary),
		enif_make_int(env, size)
	);
}

// int xlBookAddPicture(BookHandle handle, const wchar_t* filename);
ERL_NIF_TERM c_xlBookAddPicture(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	ErlNifBinary filename_temp;

	if(enif_inspect_binary(env, argv[1], &filename_temp) < 1) {
		return enif_make_badarg(env);
	}

	unsigned char *pt = createNullTermMbString(filename_temp);

	if(!pt) {
		return enif_make_badarg(env);
	}

	size_t mbs_len = strlen((const char*)pt);

	size_t character_count = mbstowcs(NULL, (const char*)pt, mbs_len);

	wchar_t w_filename[character_count + 1];

	(void)memset(w_filename, '\0', sizeof(w_filename) / sizeof(w_filename[0]));

	if((size_t)-1 == mbstowcs(w_filename, (const char*)pt, character_count + 1)) {
		free(pt);

		return enif_make_badarg(env);
	}

	free(pt);

	int ret = xlBookAddPicture(resource->handle, w_filename);

	return enif_make_int(env, ret);
}

// int xlBookAddPicture2(BookHandle handle, const char* data, unsigned size);
ERL_NIF_TERM c_xlBookAddPicture2(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	ErlNifBinary data;

	if(enif_inspect_binary(env, argv[1], &data) < 1) {
		return enif_make_badarg(env);
	}

	unsigned size;

	if (0 == enif_get_uint(env, argv[2], &size)) {
		return enif_make_badarg(env);
	}

	int ret = xlBookAddPicture2(resource->handle, (const char*)data.data, size);

	return enif_make_int(env, ret);
}

// int xlBookAddPictureAsLink(BookHandle handle, const wchar_t* filename, int insert);
ERL_NIF_TERM c_xlBookAddPictureAsLink(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	ErlNifBinary filename_temp;

	if(enif_inspect_binary(env, argv[1], &filename_temp) < 1) {
		return enif_make_badarg(env);
	}

	unsigned char *pt = createNullTermMbString(filename_temp);

	if(!pt) {
		return enif_make_badarg(env);
	}

	size_t mbs_len = strlen((const char*)pt);

	size_t character_count = mbstowcs(NULL, (const char*)pt, mbs_len);

	wchar_t w_filename[character_count + 1];

	(void)memset(w_filename, '\0', sizeof(w_filename) / sizeof(w_filename[0]));

	if((size_t)-1 == mbstowcs(w_filename, (const char*)pt, character_count + 1)) {
		free(pt);

		return enif_make_badarg(env);
	}

	free(pt);

	int insert;

	if (0 == enif_get_int(env, argv[2], &insert)) {
		return enif_make_badarg(env);
	}

	int ret = xlBookAddPictureAsLink(resource->handle, w_filename, insert);

	return enif_make_int(env, ret);
}

// wchar_t* xlBookDefaultFont(BookHandle handle, int* fontSize);
ERL_NIF_TERM c_xlBookDefaultFont(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int font_size;

	const wchar_t *wstr = xlBookDefaultFont(resource->handle, &font_size);

	if(!wstr) {
		return enif_make_atom(env, "error");
	}

	ErlNifBinary ret = convertWcharToMbBinary(wstr);

	if(!ret.data) {
		return enif_make_atom(env, "error");
	}

	return enif_make_list2(env,
		enif_make_binary(env, &ret),
		enif_make_int(env, font_size)
	);
}

// void xlBookSetDefaultFont(BookHandle handle, const wchar_t* fontName, int fontSize);
ERL_NIF_TERM c_xlBookSetDefaultFont(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	ErlNifBinary font_name_temp;

	if(enif_inspect_binary(env, argv[1], &font_name_temp) < 1) {
		return enif_make_badarg(env);
	}

	unsigned char *pt = createNullTermMbString(font_name_temp);

	if(!pt) {
		return enif_make_badarg(env);
	}

	size_t mbs_len = strlen((const char*)pt);

	size_t character_count = mbstowcs(NULL, (const char*)pt, mbs_len);

	wchar_t w_font_name[character_count + 1];

	(void)memset(w_font_name, '\0', sizeof(w_font_name) / sizeof(w_font_name[0]));

	if((size_t)-1 == mbstowcs(w_font_name, (const char*)pt, character_count + 1)) {
		free(pt);

		return enif_make_badarg(env);
	}

	free(pt);

	int font_size;

	if (0 == enif_get_int(env, argv[2], &font_size)) {
		return enif_make_badarg(env);
	}

	xlBookSetDefaultFont(resource->handle, w_font_name, font_size);

	return enif_make_atom(env, "nil");
}

// int xlBookRefR1C1(BookHandle handle);
ERL_NIF_TERM c_xlBookRefR1C1(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int ret = xlBookRefR1C1(resource->handle);

	return enif_make_int(env, ret);
}

// void xlBookSetRefR1C1(BookHandle handle, int refR1C1);
ERL_NIF_TERM c_xlBookSetRefR1C1(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int ref_r1c1;

	if (0 == enif_get_int(env, argv[1], &ref_r1c1)) {
		return enif_make_badarg(env);
	}

	xlBookSetRefR1C1(resource->handle, ref_r1c1);

	return enif_make_atom(env, "nil");
}

// void xlBookSetKey(BookHandle handle, const wchar_t* name, const wchar_t* key);
ERL_NIF_TERM c_xlBookSetKey(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	ErlNifBinary name_temp;

	if(enif_inspect_binary(env, argv[1], &name_temp) < 1) {
		return enif_make_badarg(env);
	}

	unsigned char *pt1 = createNullTermMbString(name_temp);

	if(!pt1) {
		return enif_make_badarg(env);
	}

	size_t mbs_len1 = strlen((const char*)pt1);

	size_t character_count1 = mbstowcs(NULL, (const char*)pt1, mbs_len1);

	wchar_t w_name[character_count1 + 1];

	(void)memset(w_name, '\0', sizeof(w_name) / sizeof(w_name[0]));

	if((size_t)-1 == mbstowcs(w_name, (const char*)pt1, character_count1 + 1)) {
		free(pt1);

		return enif_make_badarg(env);
	}

	free(pt1);

	ErlNifBinary key_temp;

	if(enif_inspect_binary(env, argv[2], &key_temp) < 1) {
		return enif_make_badarg(env);
	}

	unsigned char *pt2 = createNullTermMbString(key_temp);

	if(!pt2) {
		return enif_make_badarg(env);
	}

	size_t mbs_len2 = strlen((const char*)pt2);

	size_t character_count2 = mbstowcs(NULL, (const char*)pt2, mbs_len2);

	wchar_t w_key[character_count2 + 1];

	(void)memset(w_key, '\0', sizeof(w_key) / sizeof(w_key[0]));

	if((size_t)-1 == mbstowcs(w_key, (const char*)pt2, character_count2 + 1)) {
		free(pt2);

		return enif_make_badarg(env);
	}

	free(pt2);

	xlBookSetKey(resource->handle, w_name, w_key);

	return enif_make_atom(env, "nil");
}

// int xlBookRgbMode(BookHandle handle);
ERL_NIF_TERM c_xlBookRgbMode(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int ret = xlBookRgbMode(resource->handle);

	return enif_make_int(env, ret);
}

// void xlBookSetRgbMode(BookHandle handle, int rgbMode);
ERL_NIF_TERM c_xlBookSetRgbMode(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int rgb_mode;

	if (0 == enif_get_int(env, argv[1], &rgb_mode)) {
		return enif_make_badarg(env);
	}

	xlBookSetRgbMode(resource->handle, rgb_mode);

	return enif_make_atom(env, "nil");
}

// int xlBookCalcMode(BookHandle handle);
ERL_NIF_TERM c_xlBookCalcMode(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int ret = xlBookCalcMode(resource->handle);

	return enif_make_int(env, ret);
}

// void xlBookSetCalcMode(BookHandle handle, int calcMode);
ERL_NIF_TERM c_xlBookSetCalcMode(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int calc_mode;

	if (0 == enif_get_int(env, argv[1], &calc_mode)) {
		return enif_make_badarg(env);
	}

	xlBookSetCalcMode(resource->handle, calc_mode);

	return enif_make_atom(env, "nil");
}

// int xlBookVersion(BookHandle handle);
ERL_NIF_TERM c_xlBookVersion(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int ret = xlBookVersion(resource->handle);

	return enif_make_int(env, ret);
}

// int xlBookBiffVersion(BookHandle handle);
ERL_NIF_TERM c_xlBookBiffVersion(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int ret = xlBookBiffVersion(resource->handle);

	return enif_make_int(env, ret);
}

// int xlBookIsDate1904(BookHandle handle);
ERL_NIF_TERM c_xlBookIsDate1904(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int ret = xlBookIsDate1904(resource->handle);

	return enif_make_int(env, ret);
}

// void xlBookSetDate1904(BookHandle handle, int date1904);
ERL_NIF_TERM c_xlBookSetDate1904(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int date_1904;

	if (0 == enif_get_int(env, argv[1], &date_1904)) {
		return enif_make_badarg(env);
	}

	xlBookSetDate1904(resource->handle, date_1904);

	return enif_make_atom(env, "nil");
}

// int xlBookIsTemplate(BookHandle handle);
ERL_NIF_TERM c_xlBookIsTemplate(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int ret = xlBookIsTemplate(resource->handle);

	return enif_make_int(env, ret);
}

// void xlBookSetTemplate(BookHandle handle, int tmpl);
ERL_NIF_TERM c_xlBookSetTemplate(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	int tmpl;

	if (0 == enif_get_int(env, argv[1], &tmpl)) {
		return enif_make_badarg(env);
	}

	xlBookSetTemplate(resource->handle, tmpl);

	return enif_make_atom(env, "nil");
}

// int xlBookSetLocale(BookHandle handle, const char* locale);
ERL_NIF_TERM c_xlBookSetLocale(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	ErlNifBinary locale;

	if(enif_inspect_binary(env, argv[1], &locale) < 1) {
		return enif_make_badarg(env);
	}

	int ret = xlBookSetLocale(resource->handle, (const char*)locale.data);

	return enif_make_int(env, ret);
}

// const char* xlBookErrorMessage(BookHandle handle);
ERL_NIF_TERM c_xlBookErrorMessage(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	ErlNifBinary ret;

	const char *mes = xlBookErrorMessage(resource->handle);

	enif_alloc_binary(strlen(mes), &ret);

	strcpy((char*)ret.data, mes);

	return enif_make_binary(env, &ret);
}

// void xlBookRelease(BookHandle handle);
ERL_NIF_TERM c_xlBookRelease(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
	BookType *resource = NULL;

	if (0 == enif_get_resource(env, argv[0], TypeOfBook, (void**)&resource)) {
		return enif_make_badarg(env);
	}

	xlBookRelease(resource->handle);

	return enif_make_atom(env, "nil");
}
