// Test des classes FitsBTColRead
#include "sopnamsp.h"
#include "machdefs.h"
#include <typeinfo>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
// #include <values.h>
#include <string.h>
#include <string>
#include <unistd.h>
#include "sophyainit.h"
#include "pexceptions.h"
#include "fabtcolread.h"
#include "fabtwriter.h"

#define NO_VECTOR
#define USE_EXCEPT

int main(int narg,char *arg[])
{
 SophyaInit();
 char *colname = "";
 int colnum = -1;
 int ihdu = 0;
 long blen = 100;
 long bsens = 1;
 long lpmod=1;
 double vs1,vs2; bool vsearch=false;
 char c;
 while((c = getopt(narg,arg,"hb:s:H:i:c:m:v:")) != -1) {
   switch (c) {
   case 'b' :
     sscanf(optarg,"%ld",&blen);
     break;
   case 's' :
     sscanf(optarg,"%ld",&bsens);
     break;
   case 'H' :
     sscanf(optarg,"%d",&ihdu);
     break;
   case 'i' :
     sscanf(optarg,"%d",&colnum);
     break;
   case 'c' :
     colname = optarg;
     break;
   case 'm' :
     sscanf(optarg,"%ld",&lpmod);
     if(lpmod<=0) lpmod = 1;
     break;
   case 'v' :
     sscanf(optarg,"%lf,%lf",&vs1,&vs2);
     vsearch=true;
     break;
   case 'h' :
   default :
     cout<<"cmvcolread -b buflen -s sens -H hdu -m print_modulo"
         <<" -i colnum -c colname -v vsearch1,vsearch2"
         <<" fitsread fitswrite"<<endl;
     return -1;
   }
 }
 if(optind>=narg) {
   cout<<"Donnez un nom de fichier fits"<<endl;
   return -1;
 }
 char * fitsname = arg[optind];
 char * fitswrit = NULL;
 if(optind+1<narg) fitswrit = arg[optind+1];

 FitsABTColRead* fbt=NULL;
 FitsABTWriter*  fbtw=NULL;
 if(fitswrit)
   fbtw = new FitsABTWriter(fitswrit,BINARY_TBL,3);

#ifdef USE_EXCEPT
try {
#endif

  if(strlen(colname)>0)
    fbt = new FitsABTColRead(fitsname,colname,ihdu,blen,bsens,3);
  else
    fbt = new FitsABTColRead(fitsname,colnum,ihdu,blen,bsens,3);
  fbt->SetDebug(3);
  fbt->Print(3);
  cout<<"ReadFirstRow : "<<fbt->ReadFirstRow()<<endl;
  cout<<"ReadLastRow  : "<<fbt->ReadLastRow()<<endl;

  if(fbtw) {
    fbtw->SetExtName("MON_EXTENSION");
    fbtw->AddCol("xshort",NULL,"unitS",TSHORT);
    fbtw->AddCol("xlong",NULL,"unitL",TLONG);
    fbtw->AddCol("xfloat",NULL,"unitF",TFLOAT);
    fbtw->AddCol("xdouble",NULL,"unitD",TDOUBLE);
    fbtw->AddCol("xshort2",NULL,"unitS",TSHORT);
    fbtw->SetDebug(3);
  }

  if(vsearch) {
    long mid = fbt->GetNbLine()/2;
    cout<<"Search vs1="<<vs1<<" vs2="<<vs2<<endl;
    cout<<"FirstRow: "<<fbt->FirstRow(vs1,vs2,-1)<<endl;
    cout<<"LastRow : "<<fbt->LastRow(vs1,vs2,-1)<<endl;
    cout<<"FirstRow from middle: "<<fbt->FirstRow(vs1,vs2,mid)<<endl;
    cout<<"LastRow  from middle: "<<fbt->LastRow(vs1,vs2,mid)<<endl;
  }

#ifdef NO_VECTOR
  cout<<"Writting element by elements"<<endl;
  for(long i=0;i<fbt->GetNbLine();i++) {
    double x = fbt->Read(i);
    if(i%lpmod==0) cout<<i<<": "<<x<<endl;
    if(fbtw) {
      fbtw->Write(0,i,x); // Si overflow la conversion est faite par cfitsio
      fbtw->Write(1,i,x);
      fbtw->Write(2,i,x);
      fbtw->Write(3,i,x);
      fbtw->Write(4,i,(short)x); // Si overflow la conversion est faite par le system
    }
  }
#else
  cout<<"Writting with vectors"<<endl;
  TVector<double> data;
  TVector<float> dataf;
  TVector<int_4> datal;
  long istep = fbt->GetNbLine()/10; if(istep>1000) istep=1000;
  for(long i=0;i<fbt->GetNbLine();i+=istep) {
    long i2=i+istep-1; if(i2>=fbt->GetNbLine()) i2=fbt->GetNbLine()-1;
    long n = fbt->Read(i,i2,data);
    fbt->Read(i,i2,dataf);
    fbt->Read(i,i2,datal);
    cout<<i<<" n="<<n<<" ("<<data.Size()<<")"
        <<" d="<<data(0)<<","<<data(n-1)
        <<" f="<<dataf(0)<<","<<dataf(n-1)
        <<" l="<<datal(0)<<","<<datal(n-1)
        <<endl;
    if(fbtw) {
      fbtw->Write(1,i,datal);
      fbtw->Write(2,i,dataf);
      fbtw->Write(3,i,data);
    }
  }
#endif

  fbt->Print(3);

  //FitsABTColRead fbt2(*fbt);
  //fbt2.SetDebug(3);
  //fbt2.Print(3);
  //cout<<"Read(0):   "<<fbt2.Read(0)<<endl;
  //cout<<"Read(n-1): "<<fbt2.Read(fbt2.GetNbLine()-1)<<endl;
  //fbt2.Print(3);

  if(fbt) delete fbt;
  if(fbtw) {
    cout<<"Number of Overflows when writing: "<<fbtw->GetNOverFlow()<<endl;
    delete fbtw;
  }

#ifdef USE_EXCEPT
} catch (PThrowable & exc) {
  cout<<"Exception : "<<(string)typeid(exc).name()
      <<" - Msg= "<<exc.Msg()<<endl;
  if(fbt) delete fbt;
  if(fbtw) delete fbtw;
  return -2;

} catch (...) {
  cout<<" some other exception was caught !"<<endl;
  if(fbt) delete fbt;
  if(fbtw) delete fbtw;
  return -2;
}
#endif

 return 0;
}
