#include "brp_lib/platform.h"

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <wincrypt.h>
#include <shlobj.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


// Helper function to normalize path separators to backslashes for Windows API
static char* normalize_path_separators(const char *path)
{
	if (path == NULL)
		return NULL;

	char *normalized_path = _strdup(path);
	if (normalized_path == NULL)
		return NULL;

	char *p = normalized_path;
	while (*p) {
		if (*p == '/')
			*p = '\\';
		p++;
	}

	return normalized_path;
}


BRP_LIB brp_time brp_get_time(void)
{
	return (brp_time) GetTickCount();
}


BRP_LIB bool brp_get_random(brp_buf buf, size_t len)
{
    HCRYPTPROV prov;
    if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL,
    		CRYPT_VERIFYCONTEXT)) {
        return false;
    }

    CryptGenRandom(prov, (DWORD) len, (BYTE *)buf);
    CryptReleaseContext(prov, 0);
	return true;
}


BRP_LIB bool brp_get_home_dir(char * result)
{
	return SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_PROFILE, NULL, 0,result));
}


BRP_LIB bool brp_get_process_name(char * result)
{
	return ERROR_INSUFFICIENT_BUFFER !=
			GetModuleFileNameA(NULL, result, MAX_PATH);
}


BRP_LIB bool brp_create_directory_recursive(const char *path)
{
	if (path == NULL || *path == '\0')
		return false;

	char *normalized_path = normalize_path_separators(path);
	if (normalized_path == NULL)
		return false;

	// SHCreateDirectoryExA can create directories recursively
	int result = SHCreateDirectoryExA(NULL, normalized_path, NULL);
	free(normalized_path);
	return result == ERROR_SUCCESS || result == ERROR_ALREADY_EXISTS;
}


BRP_LIB bool brp_directory_exists(const char *path)
{
	if (path == NULL || *path == '\0')
		return false;

	char *normalized_path = normalize_path_separators(path);
	if (normalized_path == NULL)
		return false;

	DWORD attributes = GetFileAttributesA(normalized_path);
	return (attributes != INVALID_FILE_ATTRIBUTES) &&
		   (attributes & FILE_ATTRIBUTE_DIRECTORY);
}


BRP_LIB bool brp_getenv(const char *name, char *result, size_t len)
{
	if (name == NULL || result == NULL || len == 0) {
		return false;
	}

	DWORD result_size = GetEnvironmentVariableA(name, result, (DWORD)len);
	if (result_size == 0) {
		// Variable doesn't exist or error occurred
		return false;
	}
	if (result_size >= len) {
		// Buffer too small
		return false;
	}
	return true;
}
