#include "machdefs.h"
#include <stdlib.h>
#include <typeinfo>
#include <iostream>
#include <string>
#include <complex>

#include "datatype.h"

#include "nomtarradapter.h"
#include "tvector.h"
#include "pitvmaad.h"
#include "piyfxdrw.h"

#include "fioarr.h"
#include "fitstarray.h"



//----------------------------------------------------------------
// Class Adaptateur d'objet (Pour NamedObjMgr) d'objet TMatrix<T> 
//----------------------------------------------------------------


/* --Methode-- */
template <class T> 
NOMAdapter_TArray<T>::NOMAdapter_TArray(TArray<T>* o)
  : NObjMgrAdapter(o)
{
mArr = o;
}

/* --Methode-- */
template <class T> 
NOMAdapter_TArray<T>::~NOMAdapter_TArray()
{
}

/* --Methode-- */
template <class T> 
NObjMgrAdapter* NOMAdapter_TArray<T>::Clone(AnyDataObj* o)
{
TArray<T>* a = dynamic_cast<TArray<T> *>(o);
if (a) return ( new NOMAdapter_TArray<T>(a) );
return ( new NObjMgrAdapter(o) );
}

/* --Methode-- */
template <class T> 
string NOMAdapter_TArray<T>::GetDataObjType()
{
string type = "TArray< ";

// type +=  DecodeTypeIdName(typeid(T).name());
type += DataTypeInfo<T>::getTypeName();
type +=  " > ";
return(type);
}

/* --Methode-- */
template <class T> 
AnyDataObj* NOMAdapter_TArray<T>::CloneDataObj(bool share)
{
return ( new TArray<T>(*mArr, share) );
}

/* --Methode-- */
template <class T> 
void NOMAdapter_TArray<T>::ReadFits(string const & flnm)
{
  FitsInFile fis(flnm);
  fis >> (*mArr);
}

/* --Methode-- */
template <class T> 
void NOMAdapter_TArray<T>::SaveFits(string const & flnm)
{
  FitsOutFile fos(flnm);
  fos << (*mArr);
}

// ---- Specialisation pour complexes -----
DECL_TEMP_SPEC  /* equivalent a template <> , pour SGI-CC en particulier */
void NOMAdapter_TArray< complex<r_4> >::ReadFits(string const & flnm)
{
cout << " NOMAdapter_TArray< complex<r_4> >::ReadFits() - Error " 
     << " Not supported (complex data type)" << endl;
}
DECL_TEMP_SPEC  /* equivalent a template <> , pour SGI-CC en particulier */
void NOMAdapter_TArray< complex<r_4> >::SaveFits(string const & flnm)
{
cout << " NOMAdapter_TArray< complex<r_4> >::SaveFits() - Error " 
     << " Not supported (complex data type)" << endl;
}

DECL_TEMP_SPEC  /* equivalent a template <> , pour SGI-CC en particulier */
void NOMAdapter_TArray< complex<r_8> >::ReadFits(string const & flnm)
{
cout << " NOMAdapter_TArray< complex<r_8> >::ReadFits() - Error " 
     << " Not supported (complex data type)" << endl;
}
DECL_TEMP_SPEC  /* equivalent a template <> , pour SGI-CC en particulier */
void NOMAdapter_TArray< complex<r_8> >::SaveFits(string const & flnm)
{
cout << " NOMAdapter_TArray< complex<r_8> >::SaveFits() - Error " 
     << " Not supported (complex data type)" << endl;
}

/* --Methode-- */
template <class T> 
void NOMAdapter_TArray<T>::SavePPF(POutPersist& pos, string const & nom)
{
FIO_TArray<T> fio(mArr);
fio.Write(pos, nom);
}

/* --Methode-- */
template <class T> 
void NOMAdapter_TArray<T>::Print(ostream& os)
{
os << (*mArr);
}

/* --Methode-- */
template <class T> 
PIDrawer * NOMAdapter_TArray<T>::GetDrawer(string & dopt)
{
if (mArr->NbDimensions() == 1) {
  // On peut en faire un vecteur ...
  TVector<T>* v = new TVector<T>(*mArr, true);  // on partage les donnees
  dopt = "thinline," + dopt;
  return( new PIYfXDrawer( new POTVectorAdapter<T>(v, true), NULL, true) );
}
 else return(NULL);
}

/* --Methode-- */
template <class T> 
P2DArrayAdapter* NOMAdapter_TArray<T>::Get2DArray(string &)
{
if (mArr->NbDimensions() <= 2) {
  // On peut en faire un tableau 2-D ...
  TMatrix<T>* m = new TMatrix<T>(*mArr, true);  // on partage les donnees
  return ( new POTMatrixAdapter<T>(m, true) );
}
else return(NULL);
}

/* --Methode-- */
template <class T> 
NTupleInterface* NOMAdapter_TArray<T>::GetNTupleInterface(bool& adel)
{
adel = true;
return( new NTupInt_TArray<T>(mArr) );
}




// -------------------------------------------------------------

/* --Methode-- */
template <class T> 
NTupInt_TArray<T>::NTupInt_TArray(TArray<T>* a)
{
mArr = a;
}

/* --Methode-- */
template <class T> 
NTupInt_TArray<T>::~NTupInt_TArray()
{
}

/* --Methode-- */
template <class T> 
uint_4 NTupInt_TArray<T>::NbLines() const
{
return( mArr->Size() );
}

/* --Methode-- */
template <class T> 
uint_4 NTupInt_TArray<T>::NbColumns() const 
{
return(11);
}

/* --Methode-- */
template <class T> 
r_8* NTupInt_TArray<T>::GetLineD(int n) const 
{
if ((n < 0) || (n >= (int)(mArr->Size()) ) ) {
  mRet[0] = n;
  for(int i=1; i<11; i++)  mRet[i] = 0.;
}
else { 
  sa_size_t ix, iy, iz, it, iu;
  mArr->IndexAtPosition(n, ix, iy, iz, it, iu);
  mRet[0] = n;   mRet[1] = ix;  mRet[2] = iy;  
  mRet[3] = iz;  mRet[4] = it;  mRet[5] = iu;  
  mRet[6] = (*mArr)(ix,iy,iz,it,iu);
  mRet[7] = mRet[2];  mRet[8] = 0.;
  mRet[9] = mRet[2];  mRet[10] = 0.;
  }
return(mRet);
}

/* --Methode-- */
template <class T> 
string NTupInt_TArray<T>::VarList_C(const char* nx) const 
{
string nomx;
if (nx) nomx = nx;
else nomx = "_xh_";
string vardec = "double n,x,y,z,t,u,val,real,imag,mod,phas; \n";
vardec += "n = " + nomx + "[0];  x = " + nomx + "[1]; y = " + nomx + "[2]; \n"; 
vardec += "z = " + nomx + "[3];  t = " + nomx + "[4]; u = " + nomx + "[5]; \n"; 
vardec += "val = " + nomx + "[6]; \n";
vardec += "real = " + nomx + "[7];  imag = " + nomx + "[8]; \n";
vardec += "mod  = " + nomx + "[9];  phas = " + nomx + "[10]; \n";
return(vardec);
}

/* --Methode-- */
DECL_TEMP_SPEC  /* equivalent a template <> , pour SGI-CC en particulier */
r_8* NTupInt_TArray< complex<r_4> >::GetLineD(int n) const 
{
if ((n < 0) || (n >= (int)(mArr->Size()) ) ) {
  mRet[0] = n;
  for(int i=1; i<11; i++)  mRet[i] = 0.;
}
else { 
  sa_size_t ix, iy, iz, it, iu;
  mArr->IndexAtPosition(n, ix, iy, iz, it, iu);
  mRet[0] = n;   mRet[1] = ix;  mRet[2] = iy;  
  mRet[3] = iz;  mRet[4] = it;  mRet[5] = iu;  
  mRet[7] = (*mArr)(ix,iy,iz,it,iu).real();
  mRet[8] = (*mArr)(ix,iy,iz,it,iu).imag();
  mRet[3] = mRet[6] = sqrt(mRet[7]*mRet[7]+mRet[8]*mRet[8]);
  mRet[7] = atan2(mRet[8], mRet[7]);
}
return(mRet);
}

DECL_TEMP_SPEC  /* equivalent a template <> , pour SGI-CC en particulier */
r_8* NTupInt_TArray< complex<r_8> >::GetLineD(int n) const 
{
if ((n < 0) || (n >= (int)(mArr->Size()) ) ) {
  mRet[0] = n;
  for(int i=1; i<11; i++)  mRet[i] = 0.;
}
else { 
  sa_size_t ix, iy, iz, it, iu;
  mArr->IndexAtPosition(n, ix, iy, iz, it, iu);
  mRet[0] = n;   mRet[1] = ix;  mRet[2] = iy;  
  mRet[3] = iz;  mRet[4] = it;  mRet[5] = iu;  
  mRet[7] = (*mArr)(ix,iy,iz,it,iu).real();
  mRet[8] = (*mArr)(ix,iy,iz,it,iu).imag();
  mRet[3] = mRet[6] = sqrt(mRet[7]*mRet[7]+mRet[8]*mRet[8]);
  mRet[7] = atan2(mRet[8], mRet[7]);
}
return(mRet);
}


#ifdef __CXX_PRAGMA_TEMPLATES__
//#pragma define_template NOMAdapter_TArray<uint_2>
//#pragma define_template NOMAdapter_TArray<int_2>
#pragma define_template NOMAdapter_TArray<int_4>
#pragma define_template NOMAdapter_TArray<r_4>
#pragma define_template NOMAdapter_TArray<r_8>
#pragma define_template NOMAdapter_TArray< complex<r_4> >
#pragma define_template NOMAdapter_TArray< complex<r_8> >
//#pragma define_template NTupInt_TArray<uint_2>
//#pragma define_template NTupInt_TArray<int_2>
#pragma define_template NTupInt_TArray<int_4>
#pragma define_template NTupInt_TArray<r_4>
#pragma define_template NTupInt_TArray<r_8>
#pragma define_template NTupInt_TArray< complex<r_4> >
#pragma define_template NTupInt_TArray< complex<r_8> >
#endif

#if defined(ANSI_TEMPLATES) 
//template class NOMAdapter_TArray<uint_2>;
//template class NOMAdapter_TArray<int_2>;
template class NOMAdapter_TArray<int_4>;
template class NOMAdapter_TArray<r_4>;
template class NOMAdapter_TArray<r_8>;
template class NOMAdapter_TArray< complex<r_4> >;
template class NOMAdapter_TArray< complex<r_8> >;
// template class NTupInt_TArray<uint_2>;
// template class NTupInt_TArray<int_2>;
template class NTupInt_TArray<int_4>;
template class NTupInt_TArray<r_4>;
template class NTupInt_TArray<r_8>;
template class NTupInt_TArray< complex<r_4> >;
template class NTupInt_TArray< complex<r_8> >;
#endif
