#include <stdio.h>

#include "nvidia-sensors.h"

void init_nvml()
{
	nvmlReturn_t result;
	result = nvmlInit_v2();
	if (result != NVML_SUCCESS)
		printf("Could not init NVML: %s\n", nvmlErrorString(result));
}

void get_nvml_handle(struct card_info *card)
{
	nvmlReturn_t result;
	result = nvmlDeviceGetHandleByPciBusId_v2(card->pci_id, card->nvml_device);
	if (result != NVML_SUCCESS) {
		printf("Failed to get NVML device handle for card at %s: %s\n", card->pci_id, nvmlErrorString(result));
		card->nvml_device = NULL;
	}
}

void print_nvml_clock_reason(int compact, struct card_info *card)
{
	unsigned long long reasons = get_nvml_clock_reasons(card);
	int single_reason = 1;
		
	for (int i = 0; i < (sizeof(clock_reason_names) / sizeof(struct clock_reason)); i++) {
		if (reasons & clock_reason_names[i].mask) {
			if (!single_reason) {
				if (compact)
					printf(",");
				else
					printf(", ");
			}	
			single_reason = 0;
			
			if (compact)
				printf("%s", clock_reason_names[i].short_name);
			else
				printf("%s", clock_reason_names[i].long_name);
		}
	}
	
	if (single_reason)
		printf("None");
	
	if (!compact)
		printf(" (0x%llx)", reasons);
}

unsigned int get_nvml_temp(struct card_info *card)
{
	if (card->nvml_device == NULL)
		return 0;
	
	unsigned int temp;
	nvmlReturn_t result = nvmlDeviceGetTemperature(*(nvmlDevice_t*)(card->nvml_device), NVML_TEMPERATURE_GPU, &temp); 
	if (result != NVML_SUCCESS) {
		printf("Failed to get temperature for card at %s: %s\n", card->pci_id, nvmlErrorString(result));
		return 0;
	}
	return temp;
}

unsigned long long get_nvml_clock_reasons(struct card_info *card)
{
	if (card->nvml_device == NULL)
		return 0;
	
	unsigned long long reasons;
	nvmlReturn_t result = nvmlDeviceGetCurrentClocksEventReasons(*(nvmlDevice_t*)(card->nvml_device), &reasons) ; 
	if (result != NVML_SUCCESS) {
		printf("Failed to get clock reasons for card at %s: %s\n", card->pci_id, nvmlErrorString(result));
		return 0;
	}
	
	return reasons;
}

unsigned int get_nvml_mem_util(struct card_info *card)
{
	if (card->nvml_device == NULL)
		return 0;
	
	nvmlUtilization_t util;
	nvmlReturn_t result = nvmlDeviceGetUtilizationRates(*(nvmlDevice_t*)(card->nvml_device), &util);
	if (result != NVML_SUCCESS) {
		printf("Failed to get clock reasons for card at %s: %s\n", card->pci_id, nvmlErrorString(result));
		return 0;
	}
	
	return util.memory;
}