#include <stdio.h>
#include <string.h>
#include <ctype.h> /* tolower(), toupper(), isalpha() */
#include <stdlib.h>
#define FALSE 0
#define TRUE  1
#define BUF 4096

void show_help(void)
{
   printf("\nusage: mdc2dat OPTION filename.sac\n"\
          "extracting data cycles of MDC-files created by Balzers Quadstar 4.22 Software\n"\
		  "\nOptions:\n"\
          "\t-i\tshow information about the mdc-file\n"\
          "\t-a\tall cycles\n"\
		  "\t-s NR\tsingle cycle\n"\
          "\t-h\tthis text\n"
          "\t-v\tversion\n\n");
}


void show_version(void)
{
   printf ("mdc2dat\nVersion 0.1, 05.11.2010\nMoritz Bubek\n");
}

int getopt(char *argument,char *option)
{
   if( argument[0]=='-' && argument[1]==option[0] )
      return TRUE;
   return FALSE;
}

int getData(char *filename, int cycleX)
{
		int counter=0,i,j,k,l;
		int opt=0;
		FILE *ptr_myfile;

		ptr_myfile=fopen(filename,"r");
		if (!ptr_myfile)
		{
			printf("Unable to open file!\n");
			return 1;
		}

		int nr_cyc;  //Number of cycles 
		fseek(ptr_myfile, 100, SEEK_SET);
		fread(&nr_cyc,sizeof(int),1,ptr_myfile);


		short nr_dbc;  //number of datablocks
		fseek(ptr_myfile, 104, SEEK_SET);
		fread(&nr_dbc,sizeof(short),1,ptr_myfile);
	
		int cycle_length; //length of data cycle
		//fseek(ptr_myfile, 106, SEEK_SET);
		//fread(&cycle_length,sizeof(int),1,ptr_myfile);
		
		short nr_val;  //number of measure values in block
		fseek(ptr_myfile, 203, SEEK_SET);
		fread(&nr_val,sizeof(short),1,ptr_myfile);

		char data_fmt;  //data format
		int lengthOfData;
		fseek(ptr_myfile, 201, SEEK_SET);
		fread(&data_fmt,sizeof(char),1,ptr_myfile);
		//Datensatzlaenge bestimmen
		//spaeter erweitern
		if (data_fmt==6)
		   lengthOfData=sizeof(float);
		else
		   lengthOfData=sizeof(float);


		char cyc_type; // cycle type
		int hpos;      // header position
		int dpos;      // data position

char qq;
char threshold_type;
int nr_of_trsh_byte=0;
char title_str[256][13];

		for(j=0;j<nr_dbc;j++)
			{
			for(k=0;k<nr_val;k++)
				{
				fseek(ptr_myfile,291+25*(j+1)+33*k+1,SEEK_SET);
				title_str[k][12]='\0';
				//printf ("\n");
				for (l=0;l<12;l++)
				  {
 				  fread(&qq,sizeof(char),1,ptr_myfile);
				  //printf ("%i ",qq);
				  title_str[k][l]=qq;
				  }

				//den Threshold auslesen
				i=291+25*(j+1)+33*k+25;
				fseek(ptr_myfile,i,SEEK_SET);
 				  fread(&threshold_type,sizeof(char),1,ptr_myfile);
				  //printf ("Treshhold %i %i\n",i,threshold_type);

				  if (threshold_type=0)
				     nr_of_trsh_byte=0;

				}
			}
		
		   

// Berechnen der Groesse eines Cycles im Speicher
// time diff (ULONG)
// zusatz	(UINT)
// Datentyp
cycle_length=4+2+nr_val*(lengthOfData+nr_of_trsh_byte);


int anz;	// number of data points	
short range; //		
float x;  //Messwerte
long xl;
short xs;

int dx=0*cycle_length;


char vv='#';
if (cycleX==-1)
   {
   vv=' ';
   }

        printf("%c number of cycles %i\n",vv,nr_cyc);
		printf("%c number of data blocks %d\n",vv,nr_dbc);
		printf("%c number of values per cycle %d\n",vv,nr_val);
		printf("%c cycle Length %i\n",vv,cycle_length);

   /* Speicher reservieren für die float-Zeiger (=cycles) */
   /* und fuer die Zei */
   float ** cycle;
   unsigned long * zeit;
   float * zeitS;
   cycle = (float **)malloc(nr_cyc*sizeof(float *));
   zeit = (long *)malloc(nr_cyc*sizeof(long *));
   zeitS = (float *)malloc(nr_cyc*sizeof(float *));

   if(NULL == cycle || NULL == zeit)
      {
         printf("Not enough memory...\n");
         exit(0);
      }
   /* Jetzt noch Speicher reservieren für die einzelnen Werte der i-ten Cycle */
   for(i=0; i < nr_cyc; i++)
      {
         cycle[i] = (float *)malloc(nr_val*sizeof(float));
         if(NULL == cycle[i])
            {
               printf("Not enough memory %d\n",i);
               exit(0);
            }
      }


// nr_cyc zahl an cyclen einlesen
dpos=291+1+(25+33*nr_val)*nr_dbc;

//nr_cyc=3;

// jetzt Values auslesen
for (i=0;i<nr_cyc;i++)
  {
  dx=i*cycle_length;
  //printf ("%i\t%i\n",dpos+dx-1,cycle_length);
  
  fseek(ptr_myfile, dpos+dx, SEEK_SET);
  //Zeit einlesen
  fread(&xl,sizeof(long),1,ptr_myfile);
  zeit[i]=xl;
  // Sekundenbruchteile Variable lesen
  fread(&xs,2,1,ptr_myfile);
  zeitS[i]=xl+xs/10000.0;
    
  // jeweils zahl an einträgen
  for (counter=0;counter<nr_val;counter++)
     {
     fread(&x,sizeof(float),1,ptr_myfile);
     cycle[i][counter]=x;
     //printf ("%i\t%e\n",x);
     }
  }


// Daten ausgeben
if (cycleX==0)
  {
  // Kopf schreiben
  printf ("# measured cycle values of file %s\n",filename);
  printf ("# time");
  for (i=0;i<nr_val;i++)
     printf ("\t%s",title_str[i]);
  printf ("\n");

  for (i=0;i<nr_cyc;i++)
     {
	 printf ("%e\t", zeitS[i]);
     for (j=0;j<nr_val;j++)
        {
	    printf ("%e\t", cycle[i][j]);
	    }
     printf ("\n");
     }
  }
else if (cycleX>0)
  {
  if (cycleX > nr_val)
     cycleX=1;

	printf ("# Value %i of file %s\n",cycleX,filename);

     for (i=0;i<anz;i++)
        {
	    printf ("%e\t%e\n", zeitS[i], cycle[i][cycleX]);
	    }

  }

		fclose(ptr_myfile);
		return 0;


}



int main(int argc, char *argv[])
{
   int counter=3;
   char buffer[BUF];
   size_t len=0;
   int dx=0;

   // nur ein Argument -> Hilfe ausgeben
   if(argc == 1 || getopt(argv[1],"h") == TRUE )
      {
         show_help();
         exit(0);
      }
   else if(getopt(argv[1],"v") == TRUE)
      {
         //wenns -v ist
		 show_version();
         exit(0);
      }
   else if(argc < 3)
      {
         show_help();
         exit(0);
      }

   len=strlen(argv[2])+1;
   /*Ab argv[2] bis argv[n] alle Elemente in buffer*/
   if(len > BUF)
     {
        printf("Filename too long\n");
        exit(0);
     }
   strcpy(buffer,argv[2]);
   while(argv[counter]!=NULL)
      {
         len += strlen(argv[counter])+2;
         if(len > BUF)
            {
               printf("Buffer full\n");
               break;
            }
         strcat(buffer, " ");
         strcat(buffer, argv[counter++]);
      }

   if(getopt(argv[1],"i") == TRUE)
      getData(argv[2],-1);
   else if(getopt(argv[1],"a") == TRUE)
      getData(argv[2],0);
   else if(getopt(argv[1],"s") == TRUE)
      {
	  if (argc < 4)
	     {
		 show_help();
		 exit(0);
		 }
	  else
	    {
		int wCycle= atoi(argv[2]);
		getData(argv[3], wCycle);
		}
	  }
   else
      {
	  show_help();
	  }
   return 0;
}

