#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <dlfcn.h>
#include <pthread.h>
#include "Globals.h"
#include "adl_api.h"
#include "ls_gtk.h"
#include "ls_pth.h"

extern const char *ADL_Func_Names[LSADL_FUNCS];
extern char ADL_Func_Enabled[LSADL_FUNCS];
extern char ADL_Func_Notes[LSADL_FUNCS];
struct ADLMemoryInfo lpADLMemoryInfo;
struct AdapterInfo *lpAdapterInfo;
extern int iNumberAdapters;
extern ADLTemperature iTemperature;
extern int iAdapterIndex;
extern struct OverDrive5s od5;
extern int No_Exit;
extern pthread_t Gtk_thread_ptr;
extern pthread_t Refresh_thread_ptr;
extern pthread_mutex_t Mutex1;

int main(int argc, char **argv){
	void *so_handle = dlopen( "libatiadlxx.so", RTLD_LAZY|RTLD_GLOBAL);
	int num1 = 0;
	int ret_val = 0;
	No_Exit = 1;
	(void)DL_and_Check(so_handle);

	ret_val = LSADL_Main_Control_Create(ADL_Main_Memory_Alloc, 1);
	if(ret_val != ADL_OK){
		printf("ADL Initialization Error!\n");
		Print_Code(ret_val);
		printf("Exiting!\n");
		dlclose(so_handle);
		exit(1);
	}

	ret_val = LSADL_Adapter_NumberOfAdapters_Get(&iNumberAdapters);
	if(ret_val != ADL_OK){
		printf("Cannot get the number of adapters!\n");
		Print_Code(ret_val);
		printf("Exiting!\n");
		LSADL_Main_Control_Destroy();
		dlclose(so_handle);
		exit(1);
	}


	lpAdapterInfo = malloc(sizeof(struct AdapterInfo)*iNumberAdapters);
	(void)memset((void *)lpAdapterInfo,'\0', sizeof(struct AdapterInfo)*iNumberAdapters);
	(void)memset((void *)&lpADLMemoryInfo,'\0', sizeof(struct ADLMemoryInfo));

	ret_val = LSADL_Adapter_AdapterInfo_Get(lpAdapterInfo, sizeof(struct AdapterInfo)*iNumberAdapters);
	if(ret_val != ADL_OK){
		printf("Cannot get the number of adapter info!\n");
		Print_Code(ret_val);
		printf("Exiting!\n");
		free(lpAdapterInfo);
		LSADL_Main_Control_Destroy();
		dlclose(so_handle);
		exit(1);
	}

	printf("Num Adapters(active and non-active): %d\n", iNumberAdapters);
	iAdapterIndex = lpAdapterInfo[num1].iAdapterIndex;

	ret_val = LSADL_Adapter_MemoryInfo_Get(iAdapterIndex, &lpADLMemoryInfo);
	if(ret_val != ADL_OK){
		printf("Cannot get the number of memory info!\n");
		Print_Code(ret_val);
		printf("Exiting!\n");
		free(lpAdapterInfo);
		LSADL_Main_Control_Destroy();
		dlclose(so_handle);
		exit(1);
	}
	ret_val = LSADL_OD5_Temperature_Get(iAdapterIndex, 0, &iTemperature);
	if(ret_val != ADL_OK){
		printf("Cannot get the number of od5 temperature!\n");
		Print_Code(ret_val);
		printf("Exiting!\n");
		free(lpAdapterInfo);
		LSADL_Main_Control_Destroy();
		dlclose(so_handle);
		exit(1);
	}

	printf("Mem Size: %lld\n", lpADLMemoryInfo.iMemorySize);
	printf("Mem Type: %s\n", lpADLMemoryInfo.strMemoryType);
	printf("Mem Bandwidth: %lld\n", lpADLMemoryInfo.iMemoryBandwidth);
	printf("Temp: %d\n", iTemperature.iTemperature);

	if(Perf_Alloc() == FALSE){
		printf("Perf_Alloc: memory allocation error!\n");
		printf("Exiting!\n");
		free(lpAdapterInfo);
		LSADL_Main_Control_Destroy();
		dlclose(so_handle);
		exit(1);
	}

	gtk_init(&argc, &argv);

	if(pthread_create(&Gtk_thread_ptr, NULL, GTK_Func, NULL) != 0){
		printf("Error: pthread_create failed to launch Gtk thread !\n");
		printf("Exiting!\n");
		free(lpAdapterInfo);
		LSADL_Main_Control_Destroy();
		dlclose(so_handle);
		exit(1);
	}
	if(pthread_create(&Refresh_thread_ptr, NULL, Refresh_Func, NULL) != 0){
		printf("Error: pthread_create failed to launch Refresh thread !\n");
		printf("Exiting!\n");
		//fixme kill other thread
		free(lpAdapterInfo);
		LSADL_Main_Control_Destroy();
		dlclose(so_handle);
		exit(1);
	}
	if(pthread_join(Gtk_thread_ptr, NULL) != 0){
		printf("Error: pthread_join failed to join Gtk thread!\n");
		printf("\tExiting!\n");
		free(lpAdapterInfo);
		LSADL_Main_Control_Destroy();
		dlclose(so_handle);
		exit(1);
	}
	if(pthread_join(Refresh_thread_ptr, NULL) != 0){
		printf("Error: pthread_join failed to join Refresh thread!\n");
		printf("\tExiting!\n");
		free(lpAdapterInfo);
		LSADL_Main_Control_Destroy();
		dlclose(so_handle);
		exit(1);
	}

	if(Perf_Dealloc() == FALSE){
		printf("Perf_Delloc: memory allocation error!\n");
	}

	LSADL_Main_Control_Destroy();
	free(lpAdapterInfo);
	dlclose(so_handle);
	return 0;
}