// -*- C++ -*- 
// 
// XNTuple 
// 
// N. Regnault 03/98 
//             07/99 (NTupleInterface)
// 
// 
#ifndef XNTUPLE_H_SEEN
#define XNTUPLE_H_SEEN

#include "machdefs.h"

#include <string.h>
#include <vector>
#include <list>
#include <map>

#include "ntupintf.h"
#include "ppersist.h"
#include "dvlist.h"
#include "objfio.h"


namespace SOPHYA {
// 
// Bloc de donnees 
// 
//! \cond  Pour ne pas inclure dans la documentation
struct NTBlk
{
    NTBlk(int ndvar, int nfvar, int nivar, int nsvar, int strsz, int sz) ; 
    ~NTBlk() ; 
    
    void free() ;     // ne libere que les zones de donnees 

    int      sw ;     // swappe ? 
    long int swoff ;  // offset dans fichier de swap 
    r_4*     fdata ;  
    r_8*     ddata ;  
    int_4*   idata ;  
    char*    sdata ;  
} ; 
//! \endcond
//  Forward class declaration for Fits handler
class FITS_XNTuple;

//! Class for creation and management of data sets organised as a table
class XNTuple : public AnyDataObj , public NTupleInterface {
public:
  //    enum {classId = ClassId_XNTuple };

    XNTuple() ; 
    XNTuple(int ndvar, int nfvar, int nivar, int nsvar, 
	    char** vnames, 
	    int blk=512, int maxblk=100, int strsz=30) ; 
    XNTuple(XNTuple const& nt) ; 
    XNTuple(string const & flnm); 
    virtual           ~XNTuple();
    
    void              Fill(r_8* d_data, r_4* f_data, int_4* i_data, char** sdata);
    
    inline int_4      NEntry() const { return mNEnt ; } 
    inline int_4      NDVar() const  { return mD ; } 
    inline int_4      NFVar() const  { return mF ; } 
    inline int_4      NIVar() const  { return mI ; } 
    inline int_4      NSVar() const  { return mS ; } 
    inline int_4      NVar() const   { return mNVars ; } 
    int               IndexNom(char const* nom) const ; 
    string            NomIndex(int k) const ; 
    
    r_8               GetDVal(int i, int k) const ; 
    r_4               GetFVal(int i, int k) const ; 
    int_4             GetIVal(int i, int k) const ; 
    string            GetSVal(int i, int k) const ; 
    //    MuTyV             GetVal(char const* nom) ; 
    
    void              Copy(XNTuple const& nt) ; 
    inline XNTuple&   operator=(XNTuple const& nt) { Copy(nt) ; return *this ; } 
    
    void              Print(int num, int nmax=1) const ;
    void              Show(ostream& os) const ; 
    inline void       Show() const { Show(cout) ; } 

    DVList&           Info() ; 

// Remplissage depuis fichier ASCII 
   int		      FillFromASCIIFile(string const& fn, r_8 ddfval=0., r_4 dfval=0.,
                                        int dival=0, const char * dsval="");
        
    static  void      SetSwapPath(char* p=NULL) ; 
    string&           SwapPath() { return swp ; } 
    
// Declaration de l interface NTuple
    virtual sa_size_t NbLines() const ;
    virtual sa_size_t NbColumns() const ;
    virtual r_8 *     GetLineD(sa_size_t n) const ;
    virtual r_8	      GetCell(sa_size_t n, sa_size_t k) const ;
    virtual r_8	      GetCell(sa_size_t n, string const & nom) const ;
    virtual string    GetCelltoString(sa_size_t n, sa_size_t k) const ;
    virtual void      GetMinMax(sa_size_t k, double& min, double& max)   const ; 
    virtual void      GetMinMax(string const & nom, double& min, double& max)   const ; 
    virtual sa_size_t ColumnIndex(string const & nom)  const ;
    virtual string    ColumnName(sa_size_t k) const;
    virtual string    VarList_C(const char* nomx=NULL) const ;
    virtual string    LineHeaderToString() const;
    virtual string    LineToString(sa_size_t n) const;  

//  Pour la gestion de persistance
    friend class ObjFileIO<XNTuple> ;


  // pour fichiers FITS
    friend class FITS_XNTuple;


private:



    void    clean();    // remet tout a zero 
    void    swap() const ;    // swappe le + ancien blk en memoire 
    void    read_blk(NTBlk*) const ;  // relit le bloc 
    void    write_blk(NTBlk*) const ; // ecrit un bloc 
    void    get_blk(int i) const ;  // == unswap() 
    void    add_blk() ; // ajout d'un nouveau bloc 
    
    int_4   mNEnt ;   // nb total d'entrees 
    int_4   mNBlk ;   // nb total de blocs 
    mutable int_4   mNSwBlk ; // nb blocs swappes 
    int_4   mBlkSz ;  // taille bloc 
    int_4   mBlk ;    // bloc courant en ecriture 
    int_4   mOff ;    // offset dans bloc en ecriture ; pointe sur le premiere case vide 
    int_4   mMaxBlk ; // nb max de blocs autorises en memoire 
    int_4   mStrSz ;  // taille des variables char** 
    int_4   mNVars ;  // mD + mF + mI + mS 
    int_4   mD, mF, mI, mS ; // nb variables de chaque type 
    
    r_8* mVarD, *mMin, *mMax ; 
    
    // 
    // Noms + Prefix --> indiquer le type 
    // 
    //    char* mDNames, *mFNames, *mINames, *mSNames ; 
    char* mNames ; 
    //    typedef less<string> SCmp ; 
    //    map<string,int,SCmp> mNames ; 
    
    // Donnees 
    mutable vector<NTBlk*> ptr ; 
    mutable list<NTBlk*> sw ; // liste --> swap() 

    mutable FILE* swf ; // fichier --> swap 
    mutable char* swf_name ; 
    string  swp ; // swap_path 

    DVList* mInfo;        // Infos (variables) attachees au NTuple

    static  char*  glob_swp ; // swap_path global 
    static  long int NbNT ; 
}; 

/*! Prints table information on stream \b s (nt.Show(os)) */
inline ostream& operator << (ostream& s, XNTuple const & nt)
  {  nt.Show(s);  return(s);  }

/*! Writes the object in the POutPersist stream \b os */
inline POutPersist& operator << (POutPersist& os, XNTuple & obj)
{ ObjFileIO<XNTuple> fio(&obj);  fio.Write(os);  return(os); }
/*! Reads the object from the PInPersist stream \b is */
inline PInPersist& operator >> (PInPersist& is, XNTuple & obj)
{ ObjFileIO<XNTuple> fio(&obj); is.SkipToNextObject(); fio.Read(is); return(is); }

// Classe pour la gestion de persistance
// ObjFileIO<XNTuple>
} // namespace SOPHYA

#endif

