#include "mtapi.h"
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include <windows.h> 

void show() {
	unsigned int num = 0;
	MtapiStatus err = mtapiEnumPhysicalGpus(NULL, &num);
	if (err != MTAPI_SUCCESS) {
		printf("mtapiEnumPhysicalGpus get num error: %d\n", err);
		return;
	}
	
	printf("physical gpu nums: %d\n", num);
	MtapiPhysicalGpuHandle* handles = (MtapiPhysicalGpuHandle*)malloc(sizeof(MtapiPhysicalGpuHandle) * num);
	err = mtapiEnumPhysicalGpus(handles, &num);
	if (err != MTAPI_SUCCESS) {
		printf("mtapiEnumPhysicalGpus get handles error: %d\n", err);
	}
	else {
		for (unsigned int i = 0; i < num; i++) {
			unsigned int dispNums = 0;
			err = mtapiPhysicalGpuGetConnectedDisplay(handles[i], NULL, &dispNums);
			if (err != MTAPI_SUCCESS) {
				printf("mtapiPhysicalGpuGetConnectedDisplay get number error: %d\n", err);
			}
			else {
				printf("display nums of gpu(%d) is: %d\n", i, dispNums);
				unsigned int* ids = (unsigned int*)malloc(sizeof(unsigned int) * dispNums);
				err = mtapiPhysicalGpuGetConnectedDisplay(handles[i], ids, &dispNums);
				if (err != MTAPI_SUCCESS) {
					printf("mtapiPhysicalGpuGetConnectedDisplay get ids error: %d\n", err);
				}
				else {
					printf("display ids:");
					for (unsigned int i = 0; i < dispNums; i++) {
						printf(" %d", ids[i]);
					}
					printf("\n");
				}
				free(ids);
			}
		}
	}

	for (unsigned int i = 0; i < num; i++) {
		mtapiPhysicalGpuFree(handles[i]);
	}
	if (handles) {
		free(handles);
	}
}

void try_disp(int width, int height, int ref) {
	MtapiCustomDisplay display;
	display.vDisplay = height;
	display.hDisplay = width;
	display.vRefresh = ref;

	MtapiStatus err = mtapiDisplayTryCustomDisplay(0, display);
	if (err != MTAPI_SUCCESS) {
		printf("mtapiDisplayTryCustomDisplay width(%d), height(%d), refresh(%d), ret(%d)\n", width, height, ref, err);
	}
	else {
		printf("try display width(%d), height(%d), refresh(%d) succeed!\n", width, height, ref);
	}
}

void save(int width, int height, int ref) {
	MtapiCustomDisplay display;
	display.vDisplay = height;
	display.hDisplay = width;
	display.vRefresh = ref;

	MtapiStatus err = mtapiDisplaySaveCustomDisplay(0, display);
	if (err != MTAPI_SUCCESS) {
		printf("mtapiDisplaySaveCustomDisplay width(%d), height(%d), refresh(%d), ret(%d)\n", width, height, ref, err);
	}
	else {
		printf("save display width(%d), height(%d), refresh(%d) succeed!\n", width, height, ref);
	}
}

int main(int argc, char** argv) {
	if (argc < 2) {
		printf("usage: custom_disp -p/-t 1920 1080 60 [s]/-s 1920 1080 60\n");
		return 0;
	}

	if (strcmp(argv[1], "-p") == 0) {
		show();
		return 0;
	}

	if (strcmp(argv[1], "-l") == 0) {
		if (argc < 4) {
			printf("usage: custom_disp -l 1920 1080, means width between 640 - 1920,height between 480 - 1080\n");
			return 0;
		}
		int maxWidth = atoi(argv[2]) + 1;
		int maxHeight = atoi(argv[3]) + 1;
		FILE* fp = NULL;
		fp = fopen("test.log", "w+");
		for (unsigned long i = 0; i < 100000; i++) {
			unsigned long width = rand() % (maxWidth - 640) + 640;
			unsigned long height = rand() % (maxHeight - 480) + 480;
			//int refresh = rand() % (121 - 1) + 1;
			int refresh = 60;

			MtapiCustomDisplay display;
			display.vDisplay = height;
			display.hDisplay = width;
			display.vRefresh = refresh;

			fprintf(fp, "width: %d, height: %d, refresh: %d", width, height, refresh);
			MtapiStatus err = mtapiDisplayTryCustomDisplay(0, display);
			fprintf(fp, ", try %s", err == MTAPI_SUCCESS ? "pass" : "fail");
			if (err != MTAPI_SUCCESS) {
				break;
			}
			err = mtapiDisplaySaveCustomDisplay(0, display);
			fprintf(fp, ", save %s\n", err == MTAPI_SUCCESS ? "pass" : "fail");
			if (err != MTAPI_SUCCESS) {
				break;
			}
			if ((i + 1) % 30 == 0) {
				Sleep(30000);
			}
			else
			{
				Sleep(2000);
			}
			
		}
		fclose(fp);
		return 0;
	}

	if (argc < 5) {
		printf("usage: custom_disp -t 1920 1080 60 [s]/-s 1920 1080 60\n");
		return 0;
	}
	
	int width = atoi(argv[2]);
	int height = atoi(argv[3]);
	int refresh = atoi(argv[4]);

	if(strcmp(argv[1], "-s") == 0) {
		save(width, height, refresh);
	} else if(strcmp(argv[1], "-t") == 0) {
		try_disp(width, height, refresh);
		if (argc > 5) {
			save(width, height, refresh);
		} 
	}

	return 0;
}