#pragma once

#define DLL_ARGC_RET 		15	// index of the return value for GSCalcArg.types[]...array_dims[]

#define DLL_ARGT_EMPTY		0
#define DLL_ARGT_DOUBLE		1
#define DLL_ARGT_TEXT		2
#define DLL_ARGT_ARRAY		4
#define DLL_ARGT_IMAGE		8
#define DLL_ARGT_MESSAGE	16
#define DLL_ARGT_NONE		128

#define MAXINPUT	1024

#define ERROR1_DIV_BY_ZERO		1	// #DIV/0!
#define ERROR1_INVALID_NAME		2	// #NAME?, invalid names in formulas
#define ERROR1_NULL_VALUE		3	// #NULL!, empty intersection, empty array result
#define ERROR1_NO_DATA			4	// #N/A!, no lookup results / no data in a cell
#define ERROR1_INVALID_NUMBER	5	// #NUM!, wrong number values, overflow, underflow
#define ERROR1_INVALID_REF		6	// #REF!, wrong row/col numbers, array result exceeding the sheet
#define ERROR1_INVALID_VALUE	7	// #VALUE!, wrong argument types, too long text strings, str_stack overflow
#define ERROR1_OUT_OF_MEMORY	8	// #MEMORY!, out of memory in an array formula
#define ERROR1_ARRAY_NO_FILL	9	// #FILL!, array result area already occupied by some 'foreign' cells
#define ERROR1_ARRAY_CIRC		10	// #CIRC!, circular reference
#define ERROR1_NOT_IMPLEMENTED	11	// #IMPL! function not yet implemented
#define ERROR1_SYNTAX_ERROR		12	// #SYNTAX! wrong number of parameters, operators or an invalid name

struct ArrayItem
{
	uint8_t type;		// DLL_ARGT_EMPTY | DLL_ARGT_DOUBLE | DLL_ARGT_TEXT
	uint8_t err_code;	// ERROR1_DIV_BY_ZERO...ERROR1_SYNTAX_ERROR
	uint16_t col;		// [0, 4095]
	uint32_t row;		// [0, 12582911]
	double num;			// numeric cell
	char text[MAXINPUT + 1];// text cell; max. 1024+NULL char. utf-8 string 
};

typedef void* (__cdecl *MALLOC)(size_t s);
typedef void(__cdecl *MFREE)(void *_Memory);

typedef int(__cdecl *READ_ARRAY)(void *env, int array_index, ArrayItem *val);
typedef int(__cdecl *WRITE_ARRAY)(void *env, int array_index, ArrayItem *val);

struct GSCalcArg
{
	uint8_t types[16];		// input: as in ArrayItem::type | DLL_ARGT_ARRAY
					// output: as above | DLL_ARGT_IMAGE | DLL_ARGT_MESSAGE
	uint8_t errors[16];		// ERROR1_DIV_BY_ZERO...ERROR1_SYNTAX_ERROR
	double numbers[16];
	char *strings[16];		// input (UTF-8) strings are pre-allocated by GS-Calc and must not be overwritten
						// strings[15] used for output strings already points to a MAXINPUT+1 char. temp. buffer
	struct Dims
	{
		uint32_t cx;
		uint32_t cy;
	} array_dims[16];		// dimensions of the subsequent group together range/array arguments passed from GS-Calc
	struct
	{
		BYTE *data;			// DIB data if you return types[15] = DLL_ARGT_IMAGE; must be (de-)allocated with memory_alloc/memory_free
		size_t size;		// DIB data size
		Dims dims;			// optional resizing when displaying the image (returned either as a DIB or a file path)
		MALLOC memory_alloc;
		MFREE memory_free;
	} image;
	READ_ARRAY read_array;		// returns ArrayItem.type
	WRITE_ARRAY write_array;	// returns ArrayItem.type or -1 if the out-of-memory condition occurs 
	void *env;					// internal data that must be passed back in read_array/write_array calls
};


//typedef double(__cdecl *DLL_EXT_FUNCTION)(GSCalcArg *arg);