#ifndef __STATEFILE_MODULES_H
#define __STATEFILE_MODULES_H

#include <string>
#include "BasicTypes.hxx"
#include "ByteData.hxx"
#include "FileFormat.hxx"
#include <assert.h>
#include <ext/hash_map>
#include <string.h>
#include <iostream>

namespace StateFile {

#define STATEFILE_MODULE_DEBUG (false)

  using namespace __gnu_cxx;

/******************************
 *   Modules:                 *
 ******************************/
class Module {

private:


  uint32 version_;
  uint32 versionRange_;

  std::string name_;
  std::string contentProfile_;
  std::string contentVarNames_;
  ByteData8* extra_;
  
  ByteData32* content_;

  bool skip_;  
  bool read_;
  bool written_;

  uint8 id_;

  // module names HAVE to be a certain minimum length
  inline void nameCheck( std::string name ) {
    if (name.size() < MinimumModuleNameLength )
      assert(1);
  }


  Module( std::string name, bool skip );


public:  

  static __gnu_cxx::hash_map<std::string, Module*> singleInstance_;

  static Module* getInstance( std::string name, bool skip=false );

  ~Module( void );

  // -- GET
  uint32 byteLength_header( void );
  uint32 byteLength_content( void );
  
  bool getSkip(void) { return skip_; }
  bool getRead(void) { return read_; }

  std::string getName(void) {
    return name_;
  }
  std::string getContentProfile(void) { return contentProfile_; }
  std::string getContentVarNames(void) { return contentVarNames_; }

  ByteData8* getExtra(void) { return extra_; }
  ByteData32* getContent(void);
  uint8* getContentData(void);

  uint32 getVersion(void) { return version_; }

  bool versionCompare( uint32 other );

  // -- SET
  void setSkip( bool flag=true ) { skip_ = flag; }
  void setName( std::string name ) { nameCheck(name); name_ = name; }
  void setContentProfile( std::string name ) { contentProfile_ = name; }
  void setContentNames( std::string name ) { contentVarNames_ = name; }

  void setExtra(ByteData8* extra) { extra_ = extra; }
  void setContent(ByteData32* data) { content_ = data; }

  void setVersion( uint32 version ) { version_ = version; }
  void setVersionRange ( uint32 range ) { versionRange_ = range; }

  // -- FILES
  bool fileWrite_Content( std::fstream *file );
  bool fileWrite_Header( std::fstream *file );

  bool fileRead( std::fstream *file );

};


} /* namespace */
#endif /* __STATEFILE_MODULES_H */
