/*
 * SysInfo
 *--------------------
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

#define DEFAULTUPDATETIME 1
#define PRGVERSION "0.0.1"
#define clrscr() printf("\x1B[2J") //define a clearscreen for linux
#define TRUE 1
#define FALSE 0 

//===============================================DEKLARATIONS===============================================================

//deklarations of option-switch funktions
void switch_help(void);
void switch_verbose(void);
void switch_foobar(void);
void switch_version(void);
void switch_updatetime(void);
void switch_cputemp(void);

//deklarations of output funktions
void head(void);
void uptime(void);
void kernel_v(void);
void memory(void);
void cputemp(void);

FILE *mem_file, *version_file, *kernel_file, *uptime_file, *cputemp_file;

unsigned int start      = FALSE;   //if set the main programm will start
unsigned int updatetime = DEFAULTUPDATETIME;
unsigned int old_kernel = FALSE;
unsigned int cputemp_flag = FALSE;

struct tm *tmnow;

//=================================================MAIN================================================================

int main(int argc, char **argv)
{

  if (argc > 1) // commited argument?
  {  
    unsigned int i;  
    for (i = argc; i > 1; i--)
    {
      int option_n = i-1;
      int x=9; //number of options -1
      
      char * const options[]={"--help","-h",\
                       "--foobar","-f",\
                       "--version","-v",\
                       "--updatetime","-u",\
                       "--cputemp","-ct"};
      do
      {
        if((strcmp (argv[option_n],options[x]) == 0)||(0==x))
        {
          switch(x)
          {
            case 9:
            case 8: switch_cputemp(); 
                    break;
            case 7:
            case 6: switch_updatetime(); 
                    break;
            case 5:
            case 4: switch_version();
                    break;
            case 3:
            case 2: switch_foobar();
                    break; 
            case 1:
            default: switch_help();
          }
	  
          x=-1; //all options checked (dropout...)
	
          if((1>=option_n)&&(0==start)) //if last option is read and the prgramm should not start
	  {
	    exit(0);      //Program exit
	  }
          else      
	  {
	    // empy else because dangling else problem
	  }
        }  
        else
        {
          x-=1;
        }
      }
      while(x > -1);
  
    } //END for
  } //END Arguments  
   
  
   clrscr();

  while(1)
  {
  //drawing the output on screen
    head();
    kernel_v();
    memory();
    uptime();
    if(TRUE == cputemp_flag)
      cputemp();
       
  //time between updates [default = 1]
    sleep(updatetime);
  
    clrscr();
  } //END while
   
  return 0;
} // END MAIN

//===================================================FUNCTIONS==================================================================

//SWITCH HELP output options
void switch_help(void)
{
  //drawing the help-menu
  printf("\n\n>>>sysinfo is a versatile infomonitor<<<\n");
  printf("  usage: sysinfo [option 0] [option 1]...[option n] \n\n");
  printf("  option          long option              meaning\n");
  printf("----------------------------------------------------------------------------------\n");
  printf("  -h, -?           --help                  show this message\n");
  printf("  -v               --version               show current Version\n");
  printf("  -f               --foobar                show FooBar\n");
  printf("  -u               --updatetime            set new updatetime (default: %i sec)\n", DEFAULTUPDATETIME);
} //END HELP



void switch_foobar(void)
{
  printf(">> foobar ;)\n");
} //END switch_foobar



void switch_version(void)
{
  printf(">> SysInfo Ver.: %s\n", PRGVERSION);
} //END switch_version


void switch_updatetime(void)
{
//printf("aktuell: %s   n = %i \n\n", argv[n], n); -> DEBUG
  printf("Please enter time (sec) between update: [default %i] ", DEFAULTUPDATETIME);
  scanf("%i", &updatetime);
  start = TRUE;
} //END switch_updatetime

void switch_cputemp(void)
{
  cputemp_flag = TRUE;
  start = TRUE;
} //END switch_cputemp


void uptime(void)
{
  unsigned int uptime_unsorted = 0;
  unsigned char c;
  unsigned int DD;
  unsigned int HH;
  unsigned int MM;
//unsigned int SS; //uptime seconds
  
  uptime_file=fopen("/proc/uptime","r");

  if(NULL != uptime_file)
  {  
    while((c=fgetc(uptime_file))!= '.')
      {
        unsigned int i;
        i = atoi(&c);
        uptime_unsorted = (uptime_unsorted * 10) + i;
      }
  //SS = uptime_unsorted % 60; //seconds
    MM = uptime_unsorted / 60 % 60;
    HH = uptime_unsorted / 60 / 60 % 24;
    DD = uptime_unsorted / 60 / 60 / 24;
    fclose(uptime_file);
    printf("Uptime:\t\tdays %i, %02i:%02i\n",DD,HH,MM);
  }
  else
  {
    fclose(uptime_file);
    printf("Open file \"proc/uptime\" failed!\n");
  }

} //end UPTIME


void kernel_v(void)
{
  char Linux_v[35];
  kernel_file=fopen("/proc/sys/kernel/osrelease", "r");
  
  if(NULL != kernel_file)
  { 
    fgets(Linux_v, 35, kernel_file);
    printf("Linux:\t\t%s",Linux_v); 
    
    if(strstr(Linux_v, "2.6") == NULL )
      old_kernel = TRUE;
    
    fclose(kernel_file);
  }
  else
  {
    fclose(kernel_file);
    printf("Open file \"/proc/sys/kernel/osrelease\" failed!\n");
  }
} //END detect Kernel version and output


void memory(void)
{
  char MemTotal[35];
  char MemFree[35];
  mem_file=fopen("/proc/meminfo","r");
  
  if(NULL != mem_file)
  {
    if(old_kernel == TRUE)
    {
      unsigned char trash[100];
      unsigned int i;
      for(i=3; i>0 ; i--)
        fgets(trash, 100, mem_file);
      
    }
    
    fgets(MemTotal, 35, mem_file);
    fgets(MemFree, 35, mem_file);
    printf("%s",MemTotal);
    printf("%s",MemFree);
    fclose(mem_file);
  }
  else
  {
    fclose(mem_file);
    printf("Open file \"/proc/meminfo\" failed!\n");
  }
}//END memory


void cputemp(void)
{ 
  char cputemp_acpi[35];
  char num[] ="0123456789";
  char cputemp_char;
  int temp = 0;
  int tempbegin;
  int tempend;
  unsigned cputemp = 0;
  
  
  cputemp_file=fopen("/proc/acpi/thermal_zone/ATF0/temperature", "r");
  
  if(NULL == cputemp_file)
  {
    cputemp_file=fopen("/proc/acpi/thermal_zone/THRM/temperature","r");
    if(NULL == cputemp_file)
    {
      printf("Open file \"/proc/acpi/thermal_zone/ATF0/temperature\" failed!\n");
      printf("And open file \"/proc/acpi/thermal_zone/THRM/temperature\" failed!\n");
      
    }
  }
  if(NULL != cputemp_file)
  {
    fgets(cputemp_acpi, 35, cputemp_file);
    
  //strpbrk(cputemp, num);
  //temp = atoi(&cputemp);
       
    tempbegin = strcspn( cputemp_acpi, num);
    tempend = strcspn( cputemp_acpi, "C");
    
    int i = tempbegin;
    for (; i < (tempend-1); i++)
    {
      cputemp_char = cputemp_acpi[i];
      temp = (((int)cputemp_char)- 48);
      cputemp = (cputemp * 10) + temp;
    }
    printf("CPU-Temp:\t%d° C\n",cputemp);
    
    fclose(cputemp_file);
  }
} //END cputemp
 
 
void head(void)
{
  time_t tnow;

  time(&tnow);
  tmnow = localtime(&tnow);  
  printf("%02d.%02d.%04d                 SysInfo Ver.: %s                     %02d:%02d \n\n", tmnow -> tm_mday,
                                                                                           tmnow -> tm_mon + 1,
                                                                                           tmnow -> tm_year + 1900,
                                                                                           PRGVERSION,
                                                                                           tmnow -> tm_hour,
                                                                                           tmnow -> tm_min);
} //END head
