#include "sopnamsp.h"
#include "machdefs.h"
#include "fitslocalmap.h" 
///////////////////////////////////////////////////////////
//   Les objets delegues pour la gestion de persistance sur fichiers fits 
//    pout LocalMap
///////////////////////////////////////////////////////////
 
/*!
  \class SOPHYA::FITS_LocalMap
  \ingroup FitsIOServer
  FITS format I/O handler for SOPHYA::LocalMap objects.
*/

using namespace SOPHYA;

template <class T>
FITS_LocalMap<T>::FITS_LocalMap()
{
  dobj_= NULL;
  ownobj_=false;
}

template <class T>
FITS_LocalMap<T>::FITS_LocalMap(char inputfile[],int hdunum)
{
  dobj_=NULL;
  ownobj_=false; 
  Read(inputfile,hdunum);
}

template <class T>
FITS_LocalMap<T>::FITS_LocalMap(const LocalMap<T> & obj) 
{ 
    dobj_ = new LocalMap<T>(obj);
  ownobj_=true; 
}

template <class T>
FITS_LocalMap<T>::FITS_LocalMap(LocalMap<T> *obj) 
{ 
  dobj_ = obj;
  ownobj_=false; 
}


template <class T>
FITS_LocalMap<T>::~FITS_LocalMap()
{
  if (ownobj_ && dobj_) delete dobj_;
}


template <class T>
AnyDataObj* FITS_LocalMap<T>::DataObj()
{
  return(dobj_);
}


template <class T>
void   FITS_LocalMap<T>::SetDataObj(AnyDataObj & o) 
  {   
    LocalMap<T>* po = dynamic_cast<  LocalMap<T>* >(& o); 
    if (po == NULL) return;
    if (ownobj_ && dobj_) delete dobj_;  
    dobj_ = po; 
    ownobj_ = false; 
  }    

template <class T>
int FITS_LocalMap<T>::CheckHandling(AnyDataObj & o)
{
  if ( typeid(o) == typeid( LocalMap< T > ) ) return 2;
  LocalMap<T> * po = dynamic_cast< LocalMap<T> * >(&o);
  if (po == NULL) return 0;
  else return 1;
}

template <class T>
int FITS_LocalMap<T>::CheckReadability(FitsInOutFile& is)
{
  if (is.CurrentHDUType() !=  IMAGE_HDU ) return 0;
  string key;
  key = "Content";
  string clsnm = is.KeyValue(key);
  if (clsnm != "LocalMap") return 0;
  
  LONGLONG naxes[2];
  int naxis=2;
  int imgtyp = is.GetImageHDUInfo(naxis, naxes);
  if (naxis != 2) return 0;

  T x = 0;
  if (imgtyp == FitsTypes::ImageType(x)) return 2 ;
  else return 1;
}

template <class T>
FitsHandlerInterface* FITS_LocalMap<T>::Clone()
{
  return new FITS_LocalMap<T>() ; 
}

template <class T>
void FITS_LocalMap<T>::ReadFromFits(FitsInFile& is)
{
  if(dobj_ == NULL) 
    {
      dobj_= new LocalMap<T>;
      ownobj_= true;      
    }
  int nbentries;

  // lecture sur bin-table
  //
  //  if (!is.IsFitsTable())
  // {
  //     throw PException("ReadFromFits: the fits file seems not to be a bintable");
  //  }
  // int nbcols;
  // nbcols = is.NbColsFromFits();
  // if (nbcols != 1) 
  //  {
  //    throw IOExc("le fichier fits n'est pas une LocalMap");
  //  }
  // nbentries = is.NentriesFromFits(0);
  //

  // lecture sur image fits
  //
  if (!is.IsFitsImage())
    throw PException("ReadFromFits: the fits file seems not to be an image");
  int dimension = is.nbDimOfImage();
  if (dimension != 2 )
    cout << " WARNING::ReadFromFits: the fits image seems not to be a matrix" << endl;

  nbentries =  is.nbOfImageData();
  //

  DVList dvl=is.DVListFromFits();
  
  int_4 nSzX = dvl.GetI("NSZX");
  int_4 nSzY = dvl.GetI("NSZY");
  int_4 nPix = dvl.GetI("NPIX");
  if (nPix != nbentries)
    throw IOExc("longueur datablock incompatible avec nPix");
  dobj_->ReSize(nSzX, nSzY); 
  int_4 localMappingDone = dvl.GetI("LCMP");
  if (localMappingDone)
    {
      int_4 x0 = dvl.GetI("X0");
      int_4 y0 = dvl.GetI("Y0");
      double theta = dvl.GetD("THETA");
      double phi   = dvl.GetD("PHI");
      double angle = dvl.GetD("ANGLE");
      dobj_->SetOrigin(theta, phi, x0, y0, angle);
      double angleX = dvl.GetD("ANGLEX");
      double angleY = dvl.GetD("ANGLEY");
      dobj_->SetSize(angleX, angleY);
    }
  // On lit les DataBlocks;

  dobj_->DataBlock().ReSize(nPix);
  is.GetSingleColumn(dobj_->DataBlock().Data(),nPix);

  // dvlist de LocalMap
  dobj_->Info()  = is.DVListFromFits();
}

template <class T>
void FITS_LocalMap<T>::WriteToFits(FitsOutFile& os) 
{
  if(dobj_ == NULL) 
    { 
      cout << " WriteToFits:: dobj_= null " << endl;
      return;
    }
  int nx, ny;

  DVList dvl( dobj_->Info() );
  nx = dobj_->Size_x();  
  dvl["NSZX"] = nx;
  dvl.SetComment("NSZX", "number of pixels in x direction");
  ny = dobj_->Size_y();
  dvl["NSZY"] = ny;
  dvl.SetComment("NSZY", "number of pixels in y direction");
  dvl["NPIX"] = dobj_->NbPixels();
  dvl.SetComment("NPIX", "number of pixels in local map");

  if(dobj_->LocalMap_isDone())
    {
      dvl["LCMP"] = (int_4) 1;
      dvl.SetComment("LCMP", "local mapping 1= done, 0= not done");
      int_4 x0 = 0;
      int_4 y0 = 0;
      double theta = 0.;
      double  phi = 0.;
      double  angle = 0.;
      dobj_->Origin(theta, phi, x0, y0, angle);
      dvl["X0"]     = x0;
      dvl.SetComment("X0", "number of pixel of the origin, x direction");
      dvl["Y0"]     = y0;
      dvl.SetComment("Y0", "number of pixel of the origin, y direction");
      dvl["THETA"]  = theta;
      dvl.SetComment("THETA", "theta position of the map-origin");
      dvl["PHI"]    = phi;
      dvl.SetComment("PHI", "phi position of the map origin");
      dvl["ANGLE"]  = angle;
      dvl.SetComment("ANGLE", "angle between max x axis and sphere phi-axis");

      double angleX =0.;
      double angleY = 0.;
      dobj_->Aperture(angleX, angleY);
      dvl["ANGLEX"] = angleX;
      dvl.SetComment("ANGLEX", "sphere angle covered by map x-extension ");
      dvl["ANGLEY"] = angleY;
      dvl.SetComment("ANGLEY", "sphere angle covered by map y-extension ");
    }
  else
    {
      dvl["LCMP"] = (int_4) 0;
    }
  dvl["Content"]= "LocalMap";
  dvl.SetComment("Content", "name of SOPHYA object");
  dvl["SOPCLSNM"]= "SOPHYA::LocalMap<T>";
  dvl.SetComment("SOPCLSNM", "SOPHYA class name");
  // On ecrit les dataBlocks 
  vector<string> Noms;   
  Noms.push_back(dvl.GetS("Content"));
  //  string extname("SIMULATION");
  string extname = os.NextExtensionName();

  // sortie sur image fits
  //
  char type;
  if ( typeid(T) == typeid(r_8) ) type='D';
  else 
    if ( typeid(T) == typeid(r_4) )  type='E';
    else
      if ( typeid(T) == typeid(int_4) )  type='J';
      else
	{
	  cout <<  " type du tableau= " <<  typeid(T).name() << endl;
	  throw IOExc("FITS_LocalMap:: unknown type");
	}
  int nbdim = 2;
  int* naxisn = new int[nbdim];
  naxisn[0] = dobj_->Matrix().Size(0);
  naxisn[1] = dobj_->Matrix().Size(1);
  os.makeHeaderImageOnFits(type, nbdim, naxisn, &dvl);
  os.PutImageToFits(nx*ny, dobj_->Matrix().Data());

  delete [] naxisn;
  //

  // sortie sur bin-table fits
  //
  //  string Type;
  //  if (typeid(T) == typeid(r_8) ) Type+='D';
  //  else 
  //   if (typeid(T) == typeid(r_4) )  Type+='E';
  //   else
  //    {
  //	cout <<  " type de la LocalMap = " <<  typeid(T).name() << endl;
  //	throw IOExc("FITS_LocalMap:: unknown type");
  //    }
  //  vector<int> dummy;
  //  os.makeHeaderBntblOnFits(Type, Noms, dobj_->NbPixels(), 1, &dvl, extname, dummy);
  //  os.PutColToFits(0,  dobj_->NbPixels(), dobj_->DataBlock().Data()); 
  //

}

#ifdef __CXX_PRAGMA_TEMPLATES__
#pragma define_template FITS_LocalMap<r_8>
#pragma define_template FITS_LocalMap<r_4>
#pragma define_template FITS_LocalMap<int_4>
#endif
#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
namespace SOPHYA {
template class FITS_LocalMap<r_8>;
template class FITS_LocalMap<r_4>;
template class FITS_LocalMap<int_4>;
}
#endif
