/*$Author: friedel $*/
/*$Date: 2004/02/26 16:13:45 $*/
/*$Header: /data0/n/toaster/u/friedel/cvs/papco//papco/papco_lib/CDAWlib/CDFfromSFDU.c,v 1.2 2004/02/26 16:13:45 friedel Exp $*/
/*$Locker:  $*/
/*$Revision: 1.2 $*/
/*---------------------------------------------------------------------------*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ftw.h>
#include <errno.h>
#include <cdf.h>


FILE   *cdfs;
FILE   *logs;


/*  Handle CDFlib errors...                                  */
void errHandle (char label[], CDFstatus status)   {

  char *text;

  text = (char *) malloc (CDF_STATUSTEXT_LEN+1);
 
  if (status == 999)   
    strcpy (text, "Exit processing\n");
     
  else 
    CDFerror (status, text);

  fprintf(logs, "%s %s\n", label, text);
}



/*   Report an error if malloc doesn't work...                   */
void reportMallocError()  {

  int      status;
  char     label[CDF_STATUSTEXT_LEN+128];


  status = 999;
  strcpy (label, "ERROR allocating memory for data buffer:");
  errHandle (label, status);
  exit (status);
}


/*  Change logical source names from whatever to ALL CAPS...    */
char *allCAPS (char *string, int size)  {

  int  loop;
  char *STRING;

  STRING = (char *)  malloc (size);

  for (loop = 0; loop < size; loop++)  

    STRING[loop] = toupper (string[loop]);

  return (STRING);

}



/*   Get epoch time and date from the file in question...            */
double getZepoch (int recNumber)  {

  CDFstatus  status;
  int        CDF_stat = 0;
  double     epochData;



  status = CDFlib (SELECT_, zVAR_RECNUMBER_, recNumber,
		   GET_,    zVAR_DATA_,      &epochData,
		   NULL_);
  
  if (status != CDF_stat)  {

/*  If an error occurs, set epoch data to a bogus value    */
    epochData = -999.0;
  }

  return (epochData);  
}

/*convert SFDU date string to a CDF epoch value.
  The input string will look like: 1998-04-29T11:52:00.0Z */

double determine_epoch(char *value) {

double epoch;
int year, month, day, hour, min, sec, msec;
char Tchar[1];

/* do a formatted read to convert the values to longs, which is what's
needed for the call to computeEpoch*/

msec = 0;
sscanf(value, "%d-%d-%d%c%d:%d:%d",&year,&month,&day,Tchar, &hour,&min,&sec);
epoch = computeEPOCH(year, month, day, hour, min, sec, msec);
return(epoch);
} 


/*read_record, reads a record (one keyword=value pair) from the
 input file and puts the "keyword" into the keyword variable and
 the "value" into the value variable.  returns a status of "false"
 if the end of file is found.

TJK - modified for reading values from an SFDU file
a typical line looks like:
Project="ISTP>International Solar-Terrestrial Physics";

*/

int read_record(fp, keyword, value)
FILE *fp;
char *keyword;
char *value;
{
char record[100];
int index, index2, index3, offset, factor;
char temp[100], *temp2;

if (fgets(record, 100, fp) != NULL)
  {index = strcspn_new(record, "=");
   index3 = strcspn_new(record, "\""); /*some of the strings have " around the strings*/
   if (index >= 0)
     {strncpy(temp, record, index);
      strcpy(temp+index, "\0");
      temp2 = allCAPS (temp, index);
      strcpy(keyword, temp2);
      offset = index+2;
      factor = 1;
      if (index3 < 0) {
	offset = index+1; /* if " 's aren't present, have to adjust*/
	factor = 0;
      }
      index2 = strcspn_new(record+offset, ";");
      if (index2 > 0)
	 {strncpy(value, record+offset, index2-factor);
	  strcpy(value+index2-factor, "\0");
	  return(0);
	 } 
      else
	{/*printf("value isn't properly delimited with a semi-colon\n");
	 printf("record starting w/ the following keyword is being skipped %s \n",keyword);*/
	 return(2);
       }
    }
   else
     {/*printf("keyword isn't properly delimited with an equal sign\n");
      printf("The following record is being skipped %s \n",record);*/
      return(2);
    }

 }
else
  return(EOF);
} /* end read_record */


/*  for each .sfdu file, open, extract epoch data and logical source name..
    and create a CDF w/ the same global attributes set and at least an
    Epoch variable and one data variable (for the associated graphics file) */

int convert_sfdu (char *fileName)  {

/*  programmer:  T. Kovalick, RITSS         date:  March 12, 1999     */

  CDFid           id;
  CDFstatus       status;
  int             CDF_stat = 0;
  FILE            *sfdu;
  CDFid           newid, masterid;
  const int       mode = 1;
  const int       null = 0;
  const char      masterstring[] = {"0MASTERS"};
  CDFstatus       returnCODE = 0;
  char            cdfname[255];  
  char            master_file[255], cdfname_nodir[255];
  char            copystring[500];
  char            removestring[500];
  double          epoch;
  char            keyword[20];
  char            value[80];
  int             stat, dataset_len, baselen, rec_stat;
  int             master_len, len;
  char            *DATASET_NAME, *temp, *caps;

/*  Get what would be the logical_source name from fileName     */

    fprintf(logs, "Found sfdu: %s\n",fileName);
    temp = strrchr (fileName, '/'); /*find the last "/"*/
    dataset_len = strlen(temp) - 18;
    master_len = dataset_len;

    caps = (char *) malloc (dataset_len +1);
    DATASET_NAME = (char *) malloc (dataset_len +1);
    strncpy (cdfname_nodir, ++temp, dataset_len);
    DATASET_NAME = allCAPS (cdfname_nodir, dataset_len);
    DATASET_NAME[dataset_len] = '\0';

    /* open the associated masterCDF */

    strcpy (master_file, getenv("MASTERDIR"));
    master_len = master_len + strlen(master_file);
    strncat(master_file, cdfname_nodir,dataset_len);
    strncat(master_file, "00000000_v01.cdf", 16);
    master_len = master_len + 16;
    master_file[master_len] = '\0';

    status = CDFlib (OPEN_, CDF_, master_file, &masterid,
	  	     NULL_);

    if (status != CDF_stat) {
      errHandle (master_file, status);
    }

    if (status == CDF_stat)  {
      /*make a copy of the master w/ the correct name (to match the
	current SFDU, then modify the logical_file_id and add the
	correct values for the epoch variable).*/

      /*determine the output cdfname based on the sfdu*/

      baselen = strlen(fileName) - 4;
      strncpy(cdfname, fileName, baselen);
      strncat(cdfname, "cdf", 3);
      cdfname[baselen+3] = '\0';
      /*make a string containing the whole copy command*/

      strcpy(copystring, "cp ");
      strncat(copystring, master_file, master_len);
      strcat(copystring, " ");
      strcat(copystring, cdfname);

      stat = system(copystring); /*copy and rename file*/

      if (stat >= 0) {
	/*successfully copied the file, now make some minor changes to the 
	  global attributes and add values for the epoch variable */

	status = CDFlib (OPEN_, CDF_, cdfname, &newid,
			 SELECT_, CDF_zMODE_, 1, 
			 NULL_);
	if (status != CDF_stat) {
	  errHandle (cdfname, status);
	}
	fprintf(logs, "Creating : %s\n",cdfname);
	temp = strrchr (cdfname, '/'); /*find the last "/"*/
        len = strlen(temp);
	strncpy(cdfname_nodir, ++temp, len);

	status = CDFlib (SELECT_, ATTR_NAME_, "Logical_file_id",
			          gENTRY_, 0,
			 PUT_,    gENTRY_DATA_, CDF_CHAR, len-1, cdfname_nodir, 
			 NULL_);
	if (status != CDF_stat) {
	  errHandle (cdfname, status);
	}

	/*Find the epoch variable and select it */
	status = CDFlib (SELECT_, zVAR_NAME_, "EPOCH",
			 NULL_);
			
	if (status != CDF_stat)  {
	  status = CDFlib (SELECT_, zVAR_NAME_, "Epoch",
			   NULL_); 

	  if (status != CDF_stat)  
	    status = CDFlib (SELECT_, zVAR_NAME_, "epoch",
			     NULL_);
	}

	if (status == CDF_stat)  {
	  /*open sfdu file and read contents*/

	  sfdu = fopen(fileName, "r");

	  while ((rec_stat = read_record(sfdu, keyword, value)) >= 0)  
	    {
	      if (rec_stat == 0)
		{
		  if (strncmp(keyword, "START_DATE", 10) == 0){
		    /*convert start_date string to an epoch and then put this value
		      in the epoch variables 1st record - string will look like:
		      1998-04-29T11:52:00.0Z */
		    epoch = determine_epoch(value); 
		    status = CDFlib (SELECT_, zVAR_RECNUMBER_, 0,
				     PUT_,    zVAR_DATA_, &epoch,
				     NULL_);		    

		  }
		  else if (strncmp(keyword, "STOP_DATE", 9) == 0){
		    epoch = determine_epoch(value); 
		    status = CDFlib (SELECT_, zVAR_RECNUMBER_, 1,
				     PUT_,    zVAR_DATA_, &epoch,
				     NULL_);		    
		  }
		  
		  else if (strncmp(keyword, "REF_FILE", 8) == 0){
		    len = strlen(value);
		    status = CDFlib (SELECT_, ATTR_NAME_, "POINTER_CDF",
				              gENTRY_, 0,
				     PUT_,    gENTRY_DATA_, CDF_CHAR, len, value,
				     NULL_);		    
		  }

		  /* else printf("Do nothing for keyword %s\n",keyword);*/
		}
	    } /*endwhile*/

	  status = fclose(sfdu);
	  strcpy(removestring, "rm ");
	  strncat(removestring, fileName, strlen(fileName));
	  fprintf(logs, "removing %s\n",removestring);

/*add this when operational  stat = system(remove_string);*/ /*copy and rename file*/

	} /*endif opened new cdf and modified logical_file_id

      } /* endif stat okay for making a copy of the master*/


	status = CDFclose (masterid);
	status = CDFclose (newid);

    } /*if able to copy master sucessfully*/
      
  return(0);

    }/*end if able to open master cdf successfully*/
}

int pickout_SFDUS (char *fileName, struct stat *tree_stat, int code,
	       struct FTW *ftw_stat)  {

  char   sfduSuffix[] = {".sfdu"};
  char   master[] = {"MASTER"};
  int    check = 0;

  if (code == FTW_D)  ;

  /*  name found is a directory, move on...  */

  else if (code == FTW_DP)  
    fprintf (logs, "%s has already been processed.\n", fileName);

  else if (code == FTW_DNR ) 
  
    fprintf (logs, "%s is a directory that can't be read.\n", fileName);

  else if (code == FTW_F)  {

    if (strstr (fileName, sfduSuffix) != NULL &&
	strstr (fileName, master) == NULL)  {

      /*  Continue to process file if it's a sfdu file, but not a master... */

      check = convert_sfdu (fileName);    
      if (check != 0) fprintf (logs, "SFDU error in %s\n", fileName);

    }
  }


  else if (code == FTW_SL) 

    /*  process links to other directories...  */

    check = ftw (fileName, pickout_SFDUS);


  else if (code == FTW_NS) 
    fprintf (logs, "%s is a file where STAT function failed.\n", fileName);

  else fprintf (logs, "%s is something else.\n", fileName);

  return (0); 
}


main ()  {

  int     check;
  size_t  path_size;
  char    *LOG_file;


  /*  Open log files in the home directory  */

  path_size = strlen(getenv("META"));

  LOG_file = (char *) malloc (path_size + 9);
  if (LOG_file == NULL)  reportMallocError;

  strcpy (LOG_file, getenv("META"));

  strcat (LOG_file, "/SFDU_log");

  logs = fopen (LOG_file, "w");

  fprintf (logs, "Writing SFDU processing messages to %s\n", LOG_file);

  /*  Begin searching TOP directory for all .sfdu files...  */

  check = ftw (getenv("TOP"), pickout_SFDUS);

  fclose (logs);

}




