/*********************************************************************
*
*  Task DBSCALE
*
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <io.h>
#include <time.h>
#include <dos.h>
#include <process.h>
#include <ctype.h>
#include <signal.h>

#include "TISAN.H"

char TMPFILE[_MAX_PATH];  /* Must be visible to BREAKREQ */

main(argc,argv)
short argc;
char *argv[];
   {
   struct FILEHDR FileHeader;
   char BUFFER[sizeof(struct TXData)]; /* Largest Data Type Processed */
   struct RData *RDataPntr;
   struct TRData *TRDataPntr;
   struct XData *XDataPntr;
   struct TXData *TXDataPntr;
   double TCNT=0.;
   double TM = 1., TB = 0., DM = 1., DB = 0.;
   FILE *INSTR, *OUTSTR;
   double TMAX, TMIN, YMAX, YMIN;
   short ERRFLAG=0, IFLAG=1;
   char INFILE[_MAX_PATH], OUTFILE[_MAX_PATH];
   double TIME, DATA;
   short FLAG=0;

   signal(SIGINT,BREAKREQ);

   if (Ztskinit("DBSCALE",argv[0])) Zexit(1);

   ZBuildFileName(M_inname,INFILE);
   ZBuildFileName(M_outname,OUTFILE);
   ZBuildFileName(M_tmpname,TMPFILE);

   Zencode(2,"DBSCALE : Opening Input File '%s'\n",INFILE);
   if (((INSTR = Zopen(INFILE,O_readb)) == NULL) ||
       (!Zgethead(INSTR,&FileHeader))) Zexit(1);

   Zencode(2,"DBSCALE : Opening Scratch File '%s'\n",TMPFILE);
   if ((OUTSTR = Zopen(TMPFILE,O_writeb)) == NULL) Zexit(1);

   RDataPntr =  (struct  RData *)BUFFER;
   TRDataPntr = (struct TRData *)BUFFER;
   XDataPntr =  (struct  XData *)BUFFER;
   TXDataPntr = (struct TXData *)BUFFER;

   while (Zread(INSTR,BUFFER,FileHeader.type))
      {
      switch (FileHeader.type)
         {
         case R_Data:
            TIME = TCNT * FileHeader.m + FileHeader.b;
            DATA = RDataPntr->y;
            FLAG = RDataPntr->f;
            break;
         case TR_Data:
            TIME = TRDataPntr->t;
            DATA = TRDataPntr->y;
            break;
         case X_Data:
            TIME = TCNT * FileHeader.m + FileHeader.b;
            DATA = cabs(XDataPntr->z);
            FLAG = XDataPntr->f;
            break;
         case TX_Data:
            TIME = TXDataPntr->t;
            DATA = cabs(TXDataPntr->z);
            break;
         default:
            Zencode(10,"DBSCALE : Invalid File Type.\n");
            ERRFLAG = 1;
            goto EXIT;
         }
      ++TCNT;
      if (!FLAG)
         {
         if (IFLAG)
            {
            YMAX = DATA;
            TMAX = TIME;
            YMIN = YMAX;
            TMIN = TMAX;
            IFLAG = 0;
            }
         else
            {
            YMAX = Max(YMAX,DATA);
            YMIN = Min(YMIN,DATA);
            TMAX = Max(TMAX,TIME);
            TMIN = Min(TMIN,TIME);
            }
         }
      } /* End WHILE */

   Zencode(2,"DBSCALE : File Contains %G Points\n",TCNT);
   Zencode(3,"DBSCALE : Current TRANGE = %G, %G\n",TMIN,TMAX);
   Zencode(3,"DBSCALE : Current YRANGE = %G, %G\n",YMIN,YMAX);

   if (!Zgethead(INSTR,(struct FILEHDR *)NULL)) /* file error*/
      {
      ERRFLAG=1;
      goto EXIT;
      }

   if (TRANGE[0] < TRANGE[1])
      {
      switch(FileHeader.type)
         {
         case R_Data:
         case X_Data:
            FileHeader.b = TRANGE[0];
            if (TCNT < 2.)
               FileHeader.m = 0.;
            else
               FileHeader.m = (TRANGE[1] - TRANGE[0])/(TCNT - 1.);
            break;
         default:
            if (TMAX != TMIN)
               TM = (TRANGE[1]-TRANGE[0])/(TMAX-TMIN);
            else
               TM = 0.;

            TB = TRANGE[0] - TM*TMIN;
         }
      }

   switch(FileHeader.type)   /* Offset Time Bases */
      {
      case R_Data:
      case X_Data:
         FileHeader.b += POINT[0];
         break;
      default:
         TB += POINT[0];
      }

   if (Zputhead(OUTSTR,&FileHeader))
      {
      ERRFLAG = 1;
      goto EXIT;
      }

   if (YRANGE[0] < YRANGE[1])
      {
      if (YMAX != YMIN)
         DM = (YRANGE[1]-YRANGE[0])/(YMAX-YMIN);
      else
         DM = 0.;

      DB = YRANGE[0] - DM*YMIN;
      }

   DB += POINT[1];
   TCNT = 0.;
   IFLAG = 1;
   while (Zread(INSTR,BUFFER,FileHeader.type))
      {
      switch (FileHeader.type)
         {
         case R_Data:
            RDataPntr->y *= DM;
            RDataPntr->y += DB;
            FLAG = RDataPntr->f;
            TIME = TCNT * FileHeader.m + FileHeader.b;
            DATA = RDataPntr->y;
            break;
         case TR_Data:
            TRDataPntr->t *= TM;
            TRDataPntr->t += TB;
            TRDataPntr->y *= DM;
            TRDataPntr->y += DB;
            TIME = TRDataPntr->t;
            DATA = TRDataPntr->y;
            break;
         case X_Data:
            XDataPntr->z.x *= DM;
            XDataPntr->z.x += DB;
            XDataPntr->z.y *= DM;
            XDataPntr->z.y += DB;
            FLAG = XDataPntr->f;
            TIME = TCNT * FileHeader.m + FileHeader.b;
            DATA = cabs(XDataPntr->z);
            break;
         case TX_Data:
            TXDataPntr->t *= TM;
            TXDataPntr->t += TB;
            TXDataPntr->z.x *= DM;
            TXDataPntr->z.x += DB;
            TXDataPntr->z.y *= DM;
            TXDataPntr->z.y += DB;
            TIME = TXDataPntr->t;
            DATA = cabs(TXDataPntr->z);
            break;
         }
      if (Zwrite(OUTSTR,BUFFER,FileHeader.type))
         {
         ERRFLAG = 1;
         break;
         }
      ++TCNT;
      if (!FLAG)
         {
         if (IFLAG)
            {
            YMAX = DATA;
            TMAX = TIME;
            YMIN = YMAX;
            TMIN = TMAX;
            IFLAG = 0;
            }
         else
            {
            YMAX = Max(YMAX,DATA);
            YMIN = Min(YMIN,DATA);
            TMAX = Max(TMAX,TIME);
            TMIN = Min(TMIN,TIME);
            }
         }
      } /* End WHILE */
   if ((TRANGE[0] < TRANGE[1]) || POINT[0])
      Zencode(3,"DBSCALE : New TRANGE = %G, %G\n",TMIN,TMAX);
   if ((YRANGE[0] < YRANGE[1]) || POINT[1])
      Zencode(3,"DBSCALE : New YRANGE = %G, %G\n",YMIN,YMAX);
   if (ferror(INSTR)) ERRFLAG = 1;

EXIT:
  Zclose(INSTR);
  Zclose(OUTSTR);
  ERRFLAG = Znameout(OUTFILE,TMPFILE,ERRFLAG);
  Zexit (ERRFLAG);
  }

/***************************************************************
**
** Process ^C Interrupt
*/
short BREAKREQ()
   {
   fcloseall();
   unlink(TMPFILE);
   Zexit(3);
   }