#include "SharedMemoryController.h"

#if PLATFORM_WINDOWS
    #include "Windows/AllowWindowsPlatformTypes.h"
    #include <windows.h>
    #include <conio.h>
    #include <tchar.h>
    #pragma comment(lib, "user32.lib")

#include <stdio.h>

#define BUF_SIZE 256

TCHAR szName[] = TEXT("EPU_MDAD");
TCHAR szGPTName[] = TEXT("EPU_GPT");
TCHAR szVisemeName[] = TEXT("EPU_VISEME");
int GDebug = 0;

SharedMemoryController::SharedMemoryController()
{
	
}

SharedMemoryController::~SharedMemoryController()
{
}

TArray<FString> SharedMemoryController::OpenMDADSharedMemory()
{
	TArray<FString> mArray;
	HANDLE hMapFile = OpenFileMapping(
		FILE_MAP_ALL_ACCESS, // read/write access
		FALSE, // do not inherit the name
		szName);               // name of mapping object
	 
	if (hMapFile == NULL)
	{		
		UE_LOG(LogTemp, Warning, TEXT("Could not open file mapping object  (%d).\n"),
				 GetLastError());
		return mArray;
	}
	 
	char* pBuf = static_cast<char*>(MapViewOfFile(hMapFile, // handle to map object
												  FILE_MAP_ALL_ACCESS, // read/write permission
												  0,
												  0,
												  1024));

	int32_t* Mdad = reinterpret_cast<int32_t*>(pBuf + 1024);
	

	if (pBuf == NULL)
	{		
		UE_LOG(LogTemp, Warning, TEXT("Could not map view of file (%d).\n"),
				 GetLastError());
		CloseHandle(hMapFile);
	 
		return mArray;
	}
	//const FString myString(pBuf);
	//UE_LOG(LogTemp, Warning, TEXT("My message is %s"), *myString);
	
	//UE_LOG(LogTemp,Warning, TEXT("Test Value Exciting %d"), mdad[4]);
	//123 is the max size of the emotional array
	for (int32 i = 0; i < 123; i++) {
		mArray.Add(FString::FromInt(Mdad[i]));
	}    
	
	UnmapViewOfFile(pBuf);	 
	CloseHandle(hMapFile);

	return mArray;
}

FString SharedMemoryController::OpenGPTSharedMemory()
{
	HANDLE hMapFile = OpenFileMapping(
		FILE_MAP_ALL_ACCESS, // read/write access
		FALSE, // do not inherit the name
		szGPTName);               // name of mapping object
	 
	if (hMapFile == NULL)
	{		
		UE_LOG(LogTemp, Warning, TEXT("GPT Could not open file mapping object  (%d).\n"),
				 GetLastError());
		return "";
	}
	 
	char* pBuf = static_cast<char*>(MapViewOfFile(hMapFile, // handle to map object
												  FILE_MAP_ALL_ACCESS, // read/write permission
												  0,
												  0,
												  10000));
	if (pBuf == nullptr)
	{		
		UE_LOG(LogTemp, Warning, TEXT("Could not map view of file (%d).\n"),
				 GetLastError());
		CloseHandle(hMapFile); 
	}
	
	const FString MyString(pBuf);
	UE_LOG(LogTemp, Warning, TEXT("My message is %s"), *MyString);
	
	UnmapViewOfFile(pBuf);	 
	CloseHandle(hMapFile);

	return MyString;
}

void SharedMemoryController::OpenVisemeSharedMemory(TArray<int>& VisemeOffset, TArray<int>& VisemeID)
{
	VisemeOffset.Empty();
	VisemeID.Empty();
	int32 VISEME_ARRAY_LEN_TUPLES = 1024;
	int32 IntSize = sizeof(int32_t);
	int32_t ShmSize = IntSize + VISEME_ARRAY_LEN_TUPLES * 2 * IntSize;
	
	const HANDLE hMapFile = OpenFileMapping(
		FILE_MAP_ALL_ACCESS, // read/write access
		FALSE, // do not inherit the name
		szVisemeName);               // name of mapping object
	 
	if (hMapFile == nullptr)
	{		
		UE_LOG(LogTemp, Warning, TEXT("Viseme Could not open file mapping object  (%d).\n"),
				 GetLastError());		
	}
	 
	int32_t* pBuf = static_cast<int32_t*>(MapViewOfFile(hMapFile, // handle to map object
												  FILE_MAP_ALL_ACCESS, // read/write permission
												  0,
												  0,
												  ShmSize));	

	if (pBuf == nullptr)
	{		
		UE_LOG(LogTemp, Warning, TEXT("Could not map view of file (%d).\n"),
				 GetLastError());
		CloseHandle(hMapFile); 
		return;  // Return from the method if pBuf is equal to nullptr
	}
	

	if(pBuf[0] != 0 )
	{
		for (int32 i = 1; i < pBuf[0]*2; i += 2)
		{
			/*VisemeOffset.Add(pBuf[i]);
			VisemeID.Add(pBuf[i+1]);*/
			if (i + 1 < VISEME_ARRAY_LEN_TUPLES * 2) {
				VisemeID.Add(pBuf[i + 1]);
				VisemeOffset.Add(pBuf[i]);
			}
			else {
				UE_LOG(LogTemp, Warning, TEXT("Index out of bounds: %d"), i + 1);
			}

		}
	}	
	
	UnmapViewOfFile(pBuf);	 
	CloseHandle(hMapFile);
}

    #include "Windows/HideWindowsPlatformTypes.h"
#else
SharedMemoryController::SharedMemoryController()
{
    
}

SharedMemoryController::~SharedMemoryController()
{
}

TArray<FString> SharedMemoryController::OpenMDADSharedMemory()
{
    TArray<FString> mArray;

    return mArray;
}

FString SharedMemoryController::OpenGPTSharedMemory()
{
    return FString();
}

void SharedMemoryController::OpenVisemeSharedMemory(TArray<int>& VisemeOffset, TArray<int>& VisemeID)
{
    
}
#endif
