/*
$Id: ManyoDataIO.hh 291 2016-09-08 07:24:59Z jisuzuki $
 */

#ifndef MANYODATAIO
#define MANYODATAIO


#include "Header.hh"
#include "HeaderBase.hh"
#include "ElementContainer.hh"
#include "ElementContainerArray.hh"
#include "ElementContainerMatrix.hh"
#include "hdf5.h"

//!
/*!

 */

class ManyoDataIO
{
private:
  template <typename T> std::string tostr(const T& t);
  StringTools *st;

protected:

  void IncertAttribute( hid_t CurrentDir, const std::string &AttributeName,
                        const std::string &AttributeValue );

  hid_t CreateNewFile( const std::string &FileName, const std::string &UserName );
  hid_t CreateNewFile( const std::string &FileName, const std::string &UserName,
                       const std::string &version );
  hid_t PrepareNeXus( hid_t CurrentID );
  hid_t MakeNewDataGroup( hid_t CurrentDir, const std::string &GroupName );

  void WriteStr( ElementContainer *E,
                 hid_t CurrentGID, const std::string &DataName );
  void WriteStr( ElementContainerArray *A,
                 hid_t CurrentGID, const std::string &DataName );
  void WriteStr( ElementContainerMatrix *M,
                 hid_t CurrentGID, const std::string &DataName );

  void Write( HeaderBase *H,
              hid_t CurrentGID, const std::string &DataName );


  void Write( std::vector<Double> *vec, hid_t CurrentGID, const std::string &DataName );
  void Write( std::vector<std::string> *vec, hid_t CurrentGID, const std::string &DataName );
  void Write( std::vector<Int4>   *vec, hid_t CurrentGID, const std::string &DataName );
  void Write( std::vector<UInt4>  *vec, hid_t CurrentGID, const std::string &DataName );

  void Write( std::string *val, const UInt4 &size, hid_t CurrentGID, const std::string &DataName );
  void Write( UInt4  *val, const UInt4 &size, hid_t CurrentGID, const std::string &DataName );
  void Write( Int4   *val, const UInt4 &size, hid_t CurrentGID, const std::string &DataName );
  void Write( Double *val, const UInt4 &size, hid_t CurrentGID, const std::string &DataName );

  void Write( const std::string &val, hid_t CurrentGID, const std::string &DataName );
  void Write( UInt4  val, hid_t CurrentGID, const std::string &DataName );
  void Write( Int4   val, hid_t CurrentGID, const std::string &DataName );
  void Write( Double val, hid_t CurrentGID, const std::string &DataName );

  void Read( hid_t CurrentGID, ElementContainer *E );
  void Read( hid_t CurrentGID, ElementContainerArray *A );
  void Read( hid_t CurrentGID, ElementContainerMatrix *M );

  void Read( hid_t CurrentGID, const std::string &DataName, ElementContainer *E );
  void Read( hid_t CurrentGID, const std::string &DataName, ElementContainerArray *A );
  void Read( hid_t CurrentGID, const std::string &DataName, ElementContainerMatrix *M );

  void Read( hid_t CurrentGID, const std::string &DataName, std::vector<Double> &vd );
  void Read( hid_t CurrentGID, const std::string &DataName, UInt4 &i );
  void Read( hid_t CurrentGID, const std::string &DataName, std::string &s );
  void Read( hid_t CurrentGID, const std::string &DataName, HeaderBase &h );
  void Read( hid_t CurrentGID, const std::string &DataName, std::vector<std::string> &vs );

  void ReadVersion( hid_t CurrentGID, const std::string &DataName, std::string &s );

  bool _status;

public:
  ManyoDataIO();
 ~ManyoDataIO();

  void Write( ElementContainer *E, const std::string &FileName,
              const std::string &UserName );
  void Write( ElementContainerArray *A, const std::string &FileName,
              const std::string &UserName );
  void Write( ElementContainerMatrix *M, const std::string &FileName,
              const std::string &UserName );

  ElementContainer *ReadElementContainer( const std::string &FileName );
  ElementContainerArray *ReadElementContainerArray( const std::string &FileName );
  ElementContainerMatrix *ReadElementContainerMatrix( const std::string &FileName );

  bool Read( ElementContainer *E, const std::string &FileName );
  bool Read( ElementContainerArray *A, const std::string &FileName );
  bool Read( ElementContainerMatrix *M, const std::string &FileName );

  std::string PutDataType( const std::string &FileName );
    //!< Return a data type
    /*!<
     *   @param FileName (std::string) filename
     *   @returnValue   (std::string) ElementContainer/ElementContainerArray/ElementContainerMatrix/Unknown
    */

};

#endif
