// This may look like C code, but it is really -*- C++ -*-
// Gestion de block de donnees swapable
//          C. Magneville R. Ansari  Mai 2005
// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA
#ifndef FITSSWAPPER_H
#define FITSSWAPPER_H


#include "machdefs.h"
#include "swsegdb.h"
#include "fitsinoutfile.h"
#include "fitsblkrw.h"

#include "basedtable.h"

/*!
  \class SOPHYA::FITSDataSwapper
  \ingroup FitsIOServer
  Implementation of SOPHYA::DataSwapperInterface interface on FITS files
  (FitsInOutFile) to be used with SOPHYA::SwSegDataBlock classes.
*/

namespace SOPHYA {

template <class T> 
class FITSDataSwapper : public DataSwapperInterface<T> {
public:
  FITSDataSwapper() 
    : fcol(0) , rowos(1) , dtp(NULL)
  {
  }
  FITSDataSwapper(FitsInOutFile & ios, int col, BaseDataTable* dt=NULL) 
    : fios(ios) , fcol(col), rowos(1) , dtp(dt)
  {
  }

  inline FitsInOutFile & InOutStream() { return fios; }

  void SetInOutStream(FitsInOutFile & ios, int col) 
  {
    fios = ios;
    fcol = col;
    rowos = 1;
    /*  On ne fait pas de check sur type HDU - Reza , 30/12/2005
    if ( fios != NULL) {
      fhdu = fios->CurrentHDU();
      if (fios->CurrentHDUType() != BINARY_TBL)
	throw FitsIOException("FITSDataSwapper<T>::SetInOutStream() CurrHDU not a BINARY_TBL");
    }    */
  }

  // Operateur = , on recopie les pointeurs des streams 
  FITSDataSwapper<T>& operator = (FITSDataSwapper<T> const & a)
  {
    fios = a.fios;
    fcol = a.fcol;
    rowos = a.rowos;
    dtp = a.dtp;
  }

  virtual int_8 WriteToSwap(const T * d, size_t sz, int_8 idx, int_8 oswp=0, bool osw=false)
  {
    /* fios->MoveAbsToHDU(fhdu);  On suppose qu'on est sur le bon HDU - Reza 30/12/2005 */
    long row = rowos;
    if (osw)  row = oswp;
    if (dtp != NULL)
       if ((row+sz-1) > dtp->NRows() )  sz = dtp->NRows()-row+1;
    FitsBlockRW<T>::WriteColumnData(fios, fcol, row, 1, d, sz);
    if (!osw) rowos += sz;
    return row;
  }

  virtual void  ReadFromSwap(int_8 idx, int_8 swp, T* d, size_t sz)
  {
    long nrows = fios.GetNbRows();
    size_t szi = sz;
    if ((swp+sz-1) > nrows) sz = nrows-swp+1;  
    FitsBlockRW<T>::ReadColumnData(fios, fcol, swp, 1, d, sz);
    if (sz < szi) {
      T zz = d[sz-1];
      for(size_t k=sz; k<szi; k++)  d[k] = zz;
    }
  }

  virtual DataSwapperInterface<T>* Clone()
  {
    FITSDataSwapper<T> * rsw = new FITSDataSwapper<T>(fios, fcol, dtp) ;
    rsw->rowos = rowos;
    rsw->dtp = dtp;    
    return rsw;
  }

protected:
  FitsInOutFile fios;
  int fcol; 
  long rowos;
  BaseDataTable* dtp;
};

} // Fin du namespace

#endif
