#include <clib/dos_protos.h>
#include <dos/stdio.h>

#include <string.h>

#include "include/Messiecommon.h"
#include "include/Datasaver.h"

//--------------------------------------------------------------------
// Klasse zum Sichern der Daten, die Mess liefert
// Speichert die Daten des Messkanals in eine Datei DataX,
// die in einem Verzeichnis mit aktuellem Datum als Name liegt.
// (Vorerst zumindest). Speichert Kommentare mit Zeit unter CommentX
//
// *************** WARNUNG! ****************************
// neigt zu "Heisenbugs", Fehlern, die verschwinden, wenn man
// sie durch kommentierende Textausgabe einkreisen will
//--------------------------------------------------------------------

void Datasaver::SaveComment(char *comment,int channel) {
 if(channel < 0 || channel >= MAXCHANNELS) return;
 struct DateStamp ds;
 struct Mess_Param param;
 DateStamp(&ds);
 param.Channel=channel;
 param.Day=ds.ds_Days;
 param.Time=ds.ds_Minute*60+ds.ds_Tick/50;
 param.Value=(LONG)comment; // not portable, but who cares...
 SaveToFile(COMMENT,param,NORMAL);
}

void Datasaver::SaveData(struct Mess_Param& param) {
 if(bufferpos<buffersize) {
  buffer[bufferpos].Command=param.Command;
  buffer[bufferpos].Channel=param.Channel;
  buffer[bufferpos].Day=param.Day;
  buffer[bufferpos].Time=param.Time;
  buffer[bufferpos].Value=param.Value;
  bufferpos++;
 }
 if(bufferpos>=buffersize-1) Flush();
}

void Datasaver::Flush(void) {

 if(bufferpos) {
  for(int j=0;j<MAXCHANNELS;j++) {
   for(int i=0;i<bufferpos;i++) {
    if(buffer[i].Channel == j) {
     SaveToFile(DATA,buffer[i],TRYTOKEEPOPEN);
     buffer[i].Channel=MAXCHANNELS+1; // invalid
    }
   }
   SaveToFile(DATA,buffer[0],CLOSEIT); // ignores first 2 parameters
  }
 }
 bufferpos=0;
}

void Datasaver::SaveToFile(Datasaver::filetype sorte,Mess_Param& param,Datasaver::mode modus) {
 struct DateTime dt;
 char *filefmt=NULL;
 char *datafmt=NULL;
 char filebuf[256]; 
 char timebuf[256];
 char datebuf[256]; 
 char filenamebuf[256];
 static LONG day=0,oldday=0;
 static LONG channel=0,oldchannel=0;
 BPTR dirlock=NULL;
 static BPTR file=NULL;   
 LONG header[]={(LONG)(thisis),(LONG)location,(LONG)datebuf,(LONG)timebuf};
  
 if(modus!=TRYTOKEEPOPEN && file != NULL) {
  Close(file);
  file=NULL;
 }
 
 if(modus != CLOSEIT) {

  oldday=day;
  day=param.Day;
  oldchannel=channel;
  channel=param.Channel;
       
  dt.dat_Stamp.ds_Days=day; 
  dt.dat_Stamp.ds_Minute=(ULONG)param.Time/60;
  dt.dat_Stamp.ds_Tick=(ULONG)(param.Time % 60)*50;
  dt.dat_Format=FORMAT_DOS;
  dt.dat_Flags=0;
  dt.dat_StrDay=NULL;
  dt.dat_StrDate=(UBYTE *)datebuf;
  dt.dat_StrTime=(UBYTE *)timebuf;
    
  if(DateToStr(&dt) !=0 ) {
   if(datebuf[strlen(datebuf)-1]==' ') datebuf[strlen(datebuf)-1]='\0';
   strcpy(filenamebuf,datebuf);

   if(oldday != day || file==NULL) {
    if((dirlock=Lock((STRPTR)datebuf,SHARED_LOCK))==0) {
     if((dirlock=CreateDir((STRPTR)datebuf))==0) {
      PrintFault(IoErr(),progname);
      PrintString(MSG_DIRPROBLEM);
     }
    }
   }  

   switch(sorte) {
    case DATA:
     filefmt=GetString(MSG_DATAFILENAME);
     break;
    case COMMENT:
     filefmt=GetString(MSG_COMMENTFILENAME);
     break;
    default:
     break;
   }

   sprintf(filebuf,filefmt,channel);
     
   if(AddPart(filenamebuf,filebuf,LEN_DATSTRING+5+strlen(filebuf))==0) {
    PrintString(MSG_FILENAMEPROBLEM);
   } else {
      
    if(oldday != day || oldchannel != channel) {
     
     if(file) {
      Close(file);
      file=NULL;
     }
     
     if((file=Lock((STRPTR)filenamebuf,ACCESS_WRITE)) != 0) {
      UnLock(file);
      file=NULL;
     } else if((file=Open((STRPTR)filenamebuf,MODE_READWRITE)) != 0) {
       VFPrintf(file,GetString(MSG_HEADERTEXT),header);
       Close(file);
       file=NULL;
      }
     }

    if(file==NULL) {
     if((file=Open((STRPTR)filenamebuf,MODE_READWRITE)))
      SetVBuf(file,NULL,BUF_FULL,10000);
    }

    if(file) {

     Seek(file,0L,OFFSET_END);
     ULONG paramarray[]={0,0,0};
     paramarray[0]=param.Time;
     char fordatafmt[]="%ld %ld\n";
     char forcomfmt[]="%ld %s %s\n";

     switch(sorte) {
      case DATA:
       datafmt=fordatafmt;
       paramarray[1]=param.Value;
       break;
      case COMMENT:
       datafmt=forcomfmt;
       paramarray[1]=(ULONG)dt.dat_StrTime;
       paramarray[2]=param.Value;
       break;
     }
       
     VFPrintf(file,datafmt,(LONG *)paramarray);
       
     if(modus!=TRYTOKEEPOPEN) {
      Close(file);
      file=NULL;
     }
    } else {
     PrintFault(IoErr(),progname);
     PrintString(MSG_CANTWRITETOFILE);
    }
 
    if(dirlock) UnLock(dirlock);
   }
  }
 }
}

