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

// int xlFilterColumnIndex(FilterColumnHandle handle);
ERL_NIF_TERM c_xlFilterColumnIndex(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
	FilterColumnType *filter_column = NULL;

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

	int ret = xlFilterColumnIndex(filter_column->handle);

	return enif_make_int(env, ret);
}

// int xlFilterColumnFilterType(FilterColumnHandle handle);
ERL_NIF_TERM c_xlFilterColumnFilterType(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
	FilterColumnType *filter_column = NULL;

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

	int ret = xlFilterColumnFilterType(filter_column->handle);

	return enif_make_int(env, ret);
}

// int xlFilterColumnFilterSize(FilterColumnHandle handle);
ERL_NIF_TERM c_xlFilterColumnFilterSize(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
	FilterColumnType *filter_column = NULL;

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

	int ret = xlFilterColumnFilterSize(filter_column->handle);

	return enif_make_int(env, ret);
}

// const wchar_t* xlFilterColumnFilter(FilterColumnHandle handle, int index);
ERL_NIF_TERM c_xlFilterColumnFilter(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
	FilterColumnType *filter_column = NULL;

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

	int index;

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

	const wchar_t *wstr = xlFilterColumnFilter(filter_column->handle, index);

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

	ErlNifBinary ret = convertWcharToMbBinary(wstr);

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

	return enif_make_binary(env, &ret);
}

// void xlFilterColumnAddFilter(FilterColumnHandle handle, const wchar_t* value);
ERL_NIF_TERM c_xlFilterColumnAddFilter(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
	FilterColumnType *filter_column = NULL;

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

	ErlNifBinary value_temp;

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

	unsigned char *pt1 = createNullTermMbString(value_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_value[character_count1 + 1];

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

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

		return enif_make_badarg(env);
	}

	free(pt1);

	xlFilterColumnAddFilter(filter_column->handle, w_value);

	return enif_make_atom(env, "nil");
}

// int xlFilterColumnGetTop10(FilterColumnHandle handle, double* value, int* top, int* percent);
ERL_NIF_TERM c_xlFilterColumnGetTop10(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
	FilterColumnType *filter_column = NULL;

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

	double value;
	int top;
	int percent;

	int ret = xlFilterColumnGetTop10(filter_column->handle, &value, &top, &percent);

	return enif_make_list4(env,
		enif_make_int(env, ret),
		enif_make_double(env, value),
		enif_make_int(env, top),
		enif_make_int(env, percent)
	);
}

// void xlFilterColumnSetTop10(FilterColumnHandle handle, double value, int top, int percent);
ERL_NIF_TERM c_xlFilterColumnSetTop10(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
	FilterColumnType *filter_column = NULL;

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

	double value;

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

	int top;

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

	int percent;

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

	xlFilterColumnSetTop10(filter_column->handle, value, top, percent);

	return enif_make_atom(env, "nil");
}

// int xlFilterColumnGetCustomFilter(FilterColumnHandle handle, int* op1, const wchar_t** v1, int* op2, const wchar_t** v2, int* andOp);
ERL_NIF_TERM c_xlFilterColumnGetCustomFilter(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
	FilterColumnType *filter_column = NULL;

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

	int op1;
	const wchar_t* v1;
	int op2;
	const wchar_t* v2;
	int andOp;

	int ret = xlFilterColumnGetCustomFilter(filter_column->handle, &op1, &v1, &op2, &v2, &andOp);

	ErlNifBinary v1_tmp = {0, NULL};

	if(v1) {
		v1_tmp = convertWcharToMbBinary(v1);

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

	ErlNifBinary v2_tmp = {0, NULL};

	if(v2) {
		v2_tmp = convertWcharToMbBinary(v2);

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

	return enif_make_list6(env,
		enif_make_int(env, ret),
		enif_make_int(env, op1),
		enif_make_binary(env, &v1_tmp),
		enif_make_int(env, op2),
		enif_make_binary(env, &v2_tmp),
		enif_make_int(env, andOp)
	);
}

// void xlFilterColumnSetCustomFilter(FilterColumnHandle handle, int op, const wchar_t* val);
ERL_NIF_TERM c_xlFilterColumnSetCustomFilter(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
	FilterColumnType *filter_column = NULL;

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

	int op;

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

	ErlNifBinary val_temp;

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

	unsigned char *pt1 = createNullTermMbString(val_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_val[character_count1 + 1];

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

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

		return enif_make_badarg(env);
	}

	free(pt1);

	xlFilterColumnSetCustomFilter(filter_column->handle, op, w_val);

	return enif_make_atom(env, "nil");
}

// void xlFilterColumnSetCustomFilterEx(FilterColumnHandle handle, int op1, const wchar_t* v1, int op2, const wchar_t* v2, int andOp);
ERL_NIF_TERM c_xlFilterColumnSetCustomFilterEx(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
	FilterColumnType *filter_column = NULL;

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

	int op1;

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

	ErlNifBinary v1_temp;

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

	unsigned char *pt1 = createNullTermMbString(v1_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_v1[character_count1 + 1];

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

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

		return enif_make_badarg(env);
	}

	free(pt1);

	int op2;

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

	ErlNifBinary v2_temp;

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

	unsigned char *pt2 = createNullTermMbString(v2_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_v2[character_count2 + 1];

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

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

		return enif_make_badarg(env);
	}

	free(pt2);

	int andOp;

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

	xlFilterColumnSetCustomFilterEx(filter_column->handle, op1, w_v1, op2, w_v2, andOp);

	return enif_make_atom(env, "nil");
}

// void xlFilterColumnClear(FilterColumnHandle handle);
ERL_NIF_TERM c_xlFilterColumnClear(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
	FilterColumnType *filter_column = NULL;

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

	xlFilterColumnClear(filter_column->handle);

	return enif_make_atom(env, "nil");
}
