#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
//#include <math.h>

/*
/sys/devices/platform/it87.552/
Common settings:
  INTERVAL=5

Settings for hwmon1/device/pwm1:
  Depends on hwmon1/device/temp2_input
  Controls hwmon1/device/fan1_input
  MINTEMP=80
  MAXTEMP=100
  MINSTART=28
  MINSTOP=28
  MINPWM=0
  MAXPWM=255

Settings for hwmon1/device/pwm2:
  Depends on hwmon1/device/temp1_input
  Controls hwmon1/device/sys_input
  MINTEMP=30
  MAXTEMP=60
  MINSTART=112
  MINSTOP=100
  MINPWM=100
  MAXPWM=255



MAXTEMP=80
MINTEMP=40
MEDTEMP=60

MAXPWM=255
MINPWM=50
MEDPWM=100
HIGHPWM=200
*/

struct fan_params {
	//char *dev_dir;
	char *pwm;
	char *temp;
	//char *fan;
	char *enable;
	uint8_t curtemp;
	uint8_t maxtemp;
	uint8_t mintemp;
	uint8_t medtemp;
	uint8_t maxpwm;
	uint8_t minpwm;
	uint8_t medpwm;
	uint8_t highpwm;

	//uint8_t temp_step;
	//uint8_t temp_min;
	//uint8_t temp_max;
	//uint8_t fan_step;
	//uint8_t fan_min;
	//uint8_t fan_max;
} cpu, sys, gpu;

//uint32_t Get_Value(){}

//void Set_Value(){}


///sys/class/hwmon/hwmon1/pwm1
//

/*
system1
chipset
cpu
pciex16
vrm mos
vsoc mos
*/

int main(int argc, char **argv){
	FILE *fp;
	//struct fan_params cpu, sys, gpu;
	//uint32_t num1, num2;
//	uint16_t tmp;
	uint8_t cpupwm, gpupwm, syspwm;

	char linestring[10];
	//struct fan_params fan1, sys;

	//CPU
	cpu.pwm = malloc(strlen("/sys/class/hwmon/hwmon2/pwm1")+1);
	(void)strcpy(cpu.pwm, "/sys/class/hwmon/hwmon2/pwm1");
	cpu.temp  = malloc(strlen("/sys/class/hwmon/hwmon0/temp1_input")+1);
	(void)strcpy(cpu.temp, "/sys/class/hwmon/hwmon0/temp1_input");
	cpu.enable = malloc(strlen("/sys/class/hwmon/hwmon2/pwm1_enable")+1);
	(void)strcpy(cpu.enable, "/sys/class/hwmon/hwmon2/pwm1_enable");
	cpu.maxtemp = 60;
	cpu.mintemp = 20;
	cpu.medtemp = 40;
	cpu.maxpwm = 255;
	cpu.minpwm = 85;
	cpu.medpwm = 120;
	cpu.highpwm = 200;


	//SYS
	sys.pwm = malloc(strlen("/sys/class/hwmon/hwmon2/pwm3")+1);
	(void)strcpy(sys.pwm, "/sys/class/hwmon/hwmon2/pwm3");
	sys.temp  = malloc(strlen("/sys/class/hwmon/hwmon0/temp1_input")+1);
	(void)strcpy(sys.temp, "/sys/class/hwmon/hwmon0/temp1_input");
	sys.enable = malloc(strlen("/sys/class/hwmon/hwmon2/pwm3_enable")+1);
	(void)strcpy(sys.enable, "/sys/class/hwmon/hwmon2/pwm3_enable");
	sys.maxtemp = 60;
	sys.mintemp = 20;
	sys.medtemp = 40;
	sys.maxpwm = 255;
	sys.minpwm = 85;
	sys.medpwm = 120;
	sys.highpwm = 200;


	//GPU
	gpu.pwm = malloc(strlen("/sys/class/hwmon/hwmon1/pwm1")+1);
	(void)strcpy(gpu.pwm, "/sys/class/hwmon/hwmon1/pwm1");
	gpu.temp  = malloc(strlen("/sys/class/hwmon/hwmon1/temp1_input")+1);
	(void)strcpy(gpu.temp, "/sys/class/hwmon/hwmon1/temp1_input");
	gpu.enable = malloc(strlen("/sys/class/hwmon/hwmon1/pwm1_enable")+1);
	(void)strcpy(gpu.enable, "/sys/class/hwmon/hwmon1/pwm1_enable");
	gpu.maxtemp = 80;
	gpu.mintemp = 40;
	gpu.medtemp = 60;
	gpu.maxpwm = 255;
	gpu.minpwm = 50;
	gpu.medpwm = 100;
	gpu.highpwm = 200;


	//VRM
	//fan4.temp = malloc(strlen("/sys/class/hwmon/hwmon1/temp5_input")+1);
	//(void)strcpy(fan4.temp, "/sys/class/hwmon/hwmon1/temp5_input");


	//Enable pwm control
	if ( (fp = fopen(cpu.enable, "w")) ){
		fprintf(fp, "%u\n", 1 );
	}
	fclose(fp);

	if ( (fp = fopen(sys.enable, "w")) ){
		fprintf(fp, "%u\n", 1 );
	}
	fclose(fp);

	if ( (fp = fopen(gpu.enable, "w")) ){
		fprintf(fp, "%u\n", 1 );
	}
	fclose(fp);



	//Main loop
	while(1){

/*
		if ( (fp = fopen(cpu.temp, "r")) ){
			
		}
		fclose(fp);
*/

		//Read Temperatures

		if( ( fp = fopen(cpu.temp, "r" ) ) == NULL ) {
			fprintf( stderr, "Error opening %s\n", cpu.temp );
			cpu.curtemp = 100;
		}else{
			if( fgets(linestring, sizeof(linestring), fp) == NULL){
				fprintf( stderr, "Error reading %s\n", cpu.temp );
				cpu.curtemp = 100;
			}else{
				cpu.curtemp = atoi(linestring)/1000;
			}
		}
		fclose(fp);
		if( ( fp = fopen(sys.temp, "r" ) ) == NULL ) {
			fprintf( stderr, "Error opening %s\n", sys.temp );
			sys.curtemp = 100;
		}else{
			if( fgets(linestring, sizeof(linestring), fp) == NULL){
				fprintf( stderr, "Error reading %s\n", sys.temp );
				sys.curtemp = 100;
			}else{
				sys.curtemp = atoi(linestring)/1000;
			}
		}
		fclose(fp);
		if( ( fp = fopen(gpu.temp, "r" ) ) == NULL ) {
			fprintf( stderr, "Error opening %s\n", gpu.temp );
			gpu.curtemp = 100;
		}else{
			if( fgets(linestring, sizeof(linestring), fp) == NULL){
				fprintf( stderr, "Error reading %s\n", gpu.temp );
				gpu.curtemp = 100;
			}else{
				gpu.curtemp = atoi(linestring)/1000;
			}
		}
		fclose(fp);

/*
if [ $TEMP -lt $MINTEMP ]; then
  let TEMP=$MINPWM*$TEMP/$MINTEMP
elif [ $TEMP -lt $MEDTEMP ]; then
  let TEMP=$MEDPWM*$TEMP/$MEDTEMP
elif [ $TEMP -lt $MAXTEMP ]; then
  let TEMP=$HIGHPWM*$TEMP/$MAXTEMP
else
  let TEMP=$MAXPWM
fi
echo $TEMP > /sys/class/hwmon/hwmon1/pwm1
*/

		if(cpu.curtemp < cpu.mintemp){
			cpupwm = cpu.minpwm*cpu.curtemp/cpu.mintemp;
		}else if(cpu.curtemp < cpu.medtemp) {
			cpupwm = cpu.medpwm*cpu.curtemp/cpu.medtemp;
		}else if(cpu.curtemp < cpu.maxtemp){
			cpupwm = cpu.highpwm*cpu.curtemp/cpu.maxtemp;
		}else{
			cpupwm = cpu.maxpwm;
		}
		if ( (fp = fopen(cpu.pwm, "w")) ){
			fprintf(fp, "%u\n", cpupwm );
		}
		fclose(fp);

/*
		if(sys.curtemp < sys.mintemp){
			pwm = sys.minpwm*sys.curtemp/sys.mintemp;
		}else if(sys.curtemp < sys.medtemp) {
			pwm = sys.medpwm*sys.curtemp/sys.medtemp;
		}else if(sys.curtemp < sys.maxtemp){
			pwm = sys.highpwm*sys.curtemp/sys.maxtemp;
		}else{
			pwm = sys.maxpwm;
		}
		if ( (fp = fopen(sys.pwm, "w")) ){
			fprintf(fp, "%u\n", pwm );
		}
		fclose(fp);
*/
		if(gpu.curtemp < gpu.mintemp){
			gpupwm = gpu.minpwm*gpu.curtemp/gpu.mintemp;
		}else if(gpu.curtemp < gpu.medtemp) {
			gpupwm = gpu.medpwm*gpu.curtemp/gpu.medtemp;
		}else if(gpu.curtemp < gpu.maxtemp){
			gpupwm = gpu.highpwm*gpu.curtemp/gpu.maxtemp;
		}else{
			gpupwm = gpu.maxpwm;
		}
		if ( (fp = fopen(gpu.pwm, "w")) ){
			fprintf(fp, "%u\n", gpupwm );
		}
		fclose(fp);

		//should increase intake  if gpu above x
/*
		if( (gpupwm > 150) || (cpupwm > 150)){
			syspwm = sys.maxpwm;
		}else if(sys.curtemp < sys.mintemp){
			syspwm = sys.minpwm*sys.curtemp/sys.mintemp;
		}else if(sys.curtemp < sys.medtemp) {
			syspwm = sys.medpwm*sys.curtemp/sys.medtemp;
		}else if(sys.curtemp < sys.maxtemp){
			syspwm = sys.highpwm*sys.curtemp/sys.maxtemp;
		}else{
			syspwm = sys.maxpwm;
		}
*/

		syspwm = gpupwm>cpupwm ? gpupwm : cpupwm;

/*
		if((uint16_t)gpupwm+cpupwm > 255){
			syspwm = sys.maxpwm;
		}else{
			syspwm = gpupwm+cpupwm;
		}

*/

//		tmp = (uint16_t)gpupwm+cpupwm;
//		syspwm = (uint8_t)(tmp/2);

		//tmp = ((uint16_t)gpupwm+cpupwm)/2;
		//syspwm = (uint8_t)tmp;

		if ( (fp = fopen(sys.pwm, "w")) ){
			fprintf(fp, "%u\n", syspwm );
		}
		fclose(fp);






		sleep(1);
	}

	free(cpu.pwm);
	free(cpu.temp);
	free(cpu.enable);
	free(sys.pwm);
	free(sys.temp);
	free(sys.enable);
	free(gpu.pwm);
	free(gpu.temp);
	free(gpu.enable);

	return 0;
}
