#include "sopnamsp.h"
#include "machdefs.h"
#include <stdio.h>
#include <stdlib.h>
#include "math.h"
#include <iostream>
#include <string>
#include <vector>

#include <typeinfo>
#include "timing.h"
#include "ctimer.h"
#include "timestamp.h"
#include "histinit.h"
#include "pexceptions.h"
#include "ppfwrapstlv.h" 

/*  Programme test de la classe TimeStamp             */
/*  SOPHYA - R. Ansari (LAL)  -   Mars 2005           */

int main(int narg, char* arg[])
{
  cout << " ---- Programme ttimestamp.cc - Test classe TimeStamp --- " << endl;
  int rc = 0;
  try {
      SophyaInit();
//    PPRegister(FIO_SphereECP<r_8>);
//    DObjRegister(FIO_SphereECP<r_8>, SphereECP<r_8>);
    
    InitTim(); 
    cout << " Sizeof(TimeStamp=) " << sizeof(TimeStamp) << endl;
    TimeStamp ts; 
    cout << "ts: Now : " << ts << "(->double: " << (double)ts << " )" << endl; 
    TimeStamp ts2("26/8/1974","14:22:35.65"); 
    cout << "ts2: 26/8/1974 14:22:35.65 : " << ts2  
	 << " double->TimeStamp: " << TimeStamp(ts2.ToDays()) << endl; 
    TimeStamp ts3("08/05/1905","00:00:00"); 
    cout << "ts3: 8/05/1905 , 00:00:00 : " << ts3 << " (double): " 
	 << (double)ts3 << " double->TimeStamp: " << TimeStamp(ts3.ToDays()) << endl; 
    TimeStamp ts4("01/01/1901","03:00:20"); 
    cout << "ts3: 01/01/1901 , 03:00:20 : " << ts4 << " (double): " 
	 << (double)ts4 << " double->TimeStamp: " << TimeStamp(ts4.ToDays()) << endl; 

    TimeStamp ts5("01/12/1899","00:00:00"); 
    cout << "ts5: 01/12/1899 , 00:00:00 : " << ts5 << " (double): " 
	 << (double)ts5 << " double->TimeStamp: " << TimeStamp(ts5.ToDays()) << endl; 
    TimeStamp ts6("01/12/1899","15:30:00"); 
    cout << "ts6: 01/12/1899 , 15:30:00 : " << ts6 << " (double): " 
	 << (double)ts6 << " double->TimeStamp: " << TimeStamp(ts6.ToDays()) << endl; 

    cout << " ts.ToString(bool, bool) test : " << endl;
    cout << " ts.ToString()= " << ts.ToString() << endl;
    cout << " ts.ToString(FmtDateOnly)= " << ts.ToString(TimeStamp::FmtDateOnly) << endl;
    cout << " ts.ToString(FmtTimeOnly)= " << ts.ToString(TimeStamp::FmtTimeOnly) << endl;
    cout << " ts.ToString(FmtDateTime)= " << ts.ToString(TimeStamp::FmtDateTime) << endl;

    TimeStamp ts12("1974-08-26T14:22:35.65"); 
    cout << "ts12: 1974-08-26T14:22:35.65 : " << ts12  
	 << " double->TimeStamp: " << TimeStamp(ts12.ToDays()) << endl; 
    TimeStamp ts13("1905-05-08T00:00:00"); 
    cout << "ts13: 1905-05-08T00:00:00  " << ts13 << " (double): " 
	 << (double)ts13 << " double->TimeStamp: " << TimeStamp(ts13.ToDays()) << endl; 

    double diff;
    diff = ts12.ToDays()-ts2.ToDays();
    if (fabs(diff) > 1.e-6) {
      cout << "ttimestamp/Erreur Diff t12-t2 : Rc+=1 " << endl;
      rc += 1;
    }
    diff = ts13.ToDays()-ts3.ToDays();
    if (fabs(diff) > 1.e-6) {
      cout << "ttimestamp/Erreur Diff t13-t3 : Rc+=2 " << endl;
      rc += 2;
    }
    TimeStamp tsa("1901-1-1T14:0:0"); 
    diff = tsa.ToDays()-38./24.;
    if (fabs(diff) > 1.e-6) {
      cout << "ttimestamp/Erreur Diff tsa-38/24. : Rc+=4 " << endl;
      rc += 4;
    }
    tsa.Set("1901-02-07T18:00:00");
    diff = tsa.ToDays()-38.75;
    if (fabs(diff) > 1.e-6) {
      cout << "ttimestamp/Erreur Diff tsa-38.75 : Rc+=8 " << endl;
      rc += 8;
    }
    tsa.Set("2004-08-24T18:00:00");
    TimeStamp tsb("2004-09-03T21:00:00");
    diff = tsb.ToDays()-tsa.ToDays();
    if (fabs(diff-10.125) > 1.e-6) {
      cout << "ttimestamp/Erreur Diff tsb-tsa : Rc+=16 " << endl;
      rc += 16;
    }
    if (rc == 0)
      cout << "ttimestamp/Info CheckDiffs OK (Rc=" << rc << ")" << endl;
    else 
      cout << "ttimestamp/Erreur Pb Diffs  (Rc=" << rc << ")" << endl;

    cout << "ttimestamp/Info: Test PPF , vector<TimeStamp> " << endl;
    vector<TimeStamp> vts, vtsr;
    vts.push_back(ts);
    vts.push_back(ts2);
    vts.push_back(ts3);
    {
      POutPersist so("tts.ppf");
      so << vts;
    }
    cout << "ttimestamp/Info: Reading from tts.ppf " << endl;
    PInPersist si("tts.ppf");
    
    si >> vtsr;
    for(int kk=0; kk<vtsr.size(); kk++) {
      cout << " vtsr[" << kk << "] : " << vtsr[kk] << endl;
      diff = vtsr[kk].ToDays()-vts[kk].ToDays();
      if (fabs(diff) > 1.e-6) {
	cout << "ttimestamp/Erreur Diff   vtsr[kk]-vts[kk] : Rc+=32 " << endl;
	rc += 32;
      }
    }
    if (rc >= 32) 
      cout << "ttimestamp/Info Pb Diffs vector<TimeStamp>/PPF (Rc=" 
	   << rc << ")" << endl;
    else 
      cout << "ttimestamp/Erreur  Diffs vector<TimeStamp>/PPF OK" << endl; 

    cout << " ---- Mesure de temps ---- " << endl;
    Timer tm(false);
    for(int i=0;i<100000;i++) {
      TimeStamp tsl;
    }
    cout << "P1- Apres 100000 TimeStamp ts \n" << tm << endl;
    for(int i=0;i<100000;i++) {
      TimeStamp tsl(2009+i/365,10,i%30, 15,45,0.);
    }
    cout << "P2- Apres 100000 TimeStamp ts(y,m,d,h,m,s) \n" << tm << endl;

    double days;
    for(int i=0;i<100000;i++) {
      TimeStamp tsl;
      TimeStamp tsl2(2009+i/365,10,i%30, 15,45,0.);
      days += tsl2.ToDays()-tsl.ToDays();
    }
    cout << "P3- Apres 100000 TimeStamp t1-ts(y,m,d,h,m,s) \n" << tm << endl;

  }
  catch (PThrowable & exc) {
    cerr << " ttimestamp.cc: Catched Exception (PThrowable)" << (string)typeid(exc).name() 
	 << " - Msg= " << exc.Msg() << endl;
    rc = 99;
  }
  catch (std::exception & e) {
    cerr << " ttimestamp.cc: Catched std::xception "  
	 << " - what()= " << e.what() << endl;
    rc = 98;
  }
  catch (...) {
    cerr << " ttimestamp.cc: some other exception (...) was caught ! " << endl;
    rc = 97;
  }
  PrtTim("End ttimestamp " );
  cout << " ---- Programme ttimestamp.cc-  FIN  (Rc=" << rc << ") --- " << endl;
  return rc;
}
