#include <windows.h>
#include <stdio.h>

#define DllImport    __declspec( dllimport )
#define DllExport    __declspec( dllexport )
#define repeat(A, B) for(A=0;  A<B;  A++)

#define FILE_SIZE 1024
#define MAX_OBJECT 10
#define FLOATS_FOR_GENERAL_STUFF 20
#define FLOATS_FOR_EACH_OBJECT 10

DllExport void setup_memory_mapped_file(void);
DllExport void give_inputs_to_simulator(float zin, float zangle, float headangle, float degrees, float topdown);
DllExport void give_whiteout_values_to_simulator(float min_seconds, float max_seconds, float percent_chance);
DllExport void give_object_values_to_simulator(int object, float dampen, float return_force, float soft_force, float hard_force, float weight);
DllExport void show_tally(int value);
DllExport void start_animation(int value);

DllExport float get_zin(void);
DllExport float get_zangle(void);
DllExport float get_headangle(void);
DllExport float get_degrees(void);
DllExport float get_topdown(void);
DllExport float get_whiteout_min_seconds(void);
DllExport float get_whiteout_max_seconds(void);
DllExport float get_whiteout_percent_chance(void);
DllExport float get_tally_shown(void);
DllExport float get_animation_to_start(void);
DllExport float get_object_dampen(int object);
DllExport float get_object_return(int object);
DllExport float get_object_spring(int object);
DllExport float get_object_toothpick(int object);
DllExport float get_object_weight(int object);



HANDLE memory_mapped_file = NULL;
float* file_array = NULL;


void close_memory_mapped_file(void)
{
	UnmapViewOfFile(file_array);
    CloseHandle(memory_mapped_file); 
}

void setup_memory_mapped_file(void)
{
    int i;
    unsigned char filename[32] = "SharedByDLL.txt";
    memory_mapped_file = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, filename);
    if(memory_mapped_file == NULL)
    {
        memory_mapped_file = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, FILE_SIZE, filename);
        if(memory_mapped_file == NULL)
        {
            return;
        }
    }
	file_array = (float*) MapViewOfFile(memory_mapped_file, FILE_MAP_ALL_ACCESS, 0, 0, 0);
	if(file_array == NULL)
	{
		 return;
	}
    atexit(close_memory_mapped_file);
    repeat(i, (FILE_SIZE/4))
    {
        file_array[i] = 0.0f;
    }
    return;
}

void give_inputs_to_simulator(float zin, float zangle, float headangle, float degrees, float topdown)
{
    if(file_array != NULL)
    {        
        file_array[0] = zin;
        file_array[1] = zangle;
        file_array[2] = headangle;
        file_array[3] = degrees;
        file_array[4] = topdown;
    }
}

void give_whiteout_values_to_simulator(float min_seconds, float max_seconds, float percent_chance)
{
    if(file_array != NULL)
    {        
        file_array[5] = min_seconds;
        file_array[6] = max_seconds;
        file_array[7] = percent_chance;
    }
}

void give_object_values_to_simulator(int object, float dampen, float return_force, float soft_force, float hard_force, float weight)
{
    if(file_array != NULL && object >= 0 && object < MAX_OBJECT)
    {        
        file_array[FLOATS_FOR_GENERAL_STUFF + (object*FLOATS_FOR_EACH_OBJECT) + 0] = dampen;
        file_array[FLOATS_FOR_GENERAL_STUFF + (object*FLOATS_FOR_EACH_OBJECT) + 1] = return_force;
        file_array[FLOATS_FOR_GENERAL_STUFF + (object*FLOATS_FOR_EACH_OBJECT) + 2] = soft_force;
        file_array[FLOATS_FOR_GENERAL_STUFF + (object*FLOATS_FOR_EACH_OBJECT) + 3] = hard_force;
        file_array[FLOATS_FOR_GENERAL_STUFF + (object*FLOATS_FOR_EACH_OBJECT) + 4] = weight;
    }
}


void show_tally(int value)
{
    if(file_array != NULL)
    {        
        file_array[8] = (float) value;
    }
}

void start_animation(int value)
{
    if(file_array != NULL)
    {        
        file_array[9] = (float) value;
    }
}

float get_zin()
{
    if(file_array != NULL)
    {
        return file_array[0];
    }
    return 0.0f;
}

float get_zangle()
{
    if(file_array != NULL)
    {
        return file_array[1];
    }
    return 0.0f;
}

float get_headangle()
{
    if(file_array != NULL)
    {
        return file_array[2];
    }
    return 0.0f;
}

float get_degrees()
{
    if(file_array != NULL)
    {
        return file_array[3];
    }
    return 0.0f;
}

float get_topdown()
{
    if(file_array != NULL)
    {
        return file_array[4];
    }
    return 0.0f;
}

float get_whiteout_min_seconds()
{
    if(file_array != NULL)
    {
        return file_array[5];
    }
    return 0.0f;
}

float get_whiteout_max_seconds()
{
    if(file_array != NULL)
    {
        return file_array[6];
    }
    return 0.0f;
}

float get_whiteout_percent_chance()
{
    if(file_array != NULL)
    {
        return file_array[7];
    }
    return 0.0f;
}

float get_tally_shown()
{
    if(file_array != NULL)
    {
        return file_array[8];
    }
    return 0.0f;
}

float get_animation_to_start()
{
    float temp;
    if(file_array != NULL)
    {
        // Automatically reset to 0
        temp = file_array[9];
        file_array[9] = 0.0f;
        return temp;
    }
    return 0.0f;
}

float get_object_dampen(int object)
{
    if(file_array != NULL && object >= 0 && object < MAX_OBJECT)
    {
        return file_array[FLOATS_FOR_GENERAL_STUFF + (object*FLOATS_FOR_EACH_OBJECT) + 0];
    }
    return 0.0f;
}

float get_object_return(int object)
{
    if(file_array != NULL && object >= 0 && object < MAX_OBJECT)
    {
        return file_array[FLOATS_FOR_GENERAL_STUFF + (object*FLOATS_FOR_EACH_OBJECT) + 1];
    }
    return 0.0f;
}

float get_object_spring(int object)
{
    if(file_array != NULL && object >= 0 && object < MAX_OBJECT)
    {
        return file_array[FLOATS_FOR_GENERAL_STUFF + (object*FLOATS_FOR_EACH_OBJECT) + 2];
    }
    return 0.0f;
}

float get_object_toothpick(int object)
{
    if(file_array != NULL && object >= 0 && object < MAX_OBJECT)
    {
        return file_array[FLOATS_FOR_GENERAL_STUFF + (object*FLOATS_FOR_EACH_OBJECT) + 3];
    }
    return 0.0f;
}

float get_object_weight(int object)
{
    if(file_array != NULL && object >= 0 && object < MAX_OBJECT)
    {
        return file_array[FLOATS_FOR_GENERAL_STUFF + (object*FLOATS_FOR_EACH_OBJECT) + 4];
    }
    return 0.0f;
}
