#ifndef GDB_H
#define GDB_H

#include <iostream>
#include <fstream>
#include <math.h>
#include <string>
#include <vector>
#include <map>

using namespace std;
using std::string;

typedef map<string, string> GDB_Entry;
typedef vector<string> StringList;

class GDB
{
	string ClassType;
	bool plain_text; //only print the data matrix
	char buf[100];

public:

	string GDBfileName;

	string FORMAT_str, VARS_str;
	int VarsNumber;

	GDB_Entry EMPTY;

	map<int, string> residList;

	vector<string> REMARKS;
	vector<string> DATA;
	map<int, string> VARS;
	map<int, string> FORMAT;

	map< int, map<string, string> > Entries;

	GDB();
	GDB(const string& fileName);

	void loadGDB(const string &fileName);
	void saveGDB(const string &fileName);

	//add one VAR with given FORMAT
	void addVAR(const string &VAR_Name, const string &FORMAT_Name);
	//re-set one VAR with given FORMAT
	void setVAR(int index, const string &VAR_Name, const string &FORMAT_Name);

	//set the DATA with 'DataVal'
	void setData(const string &DataName, const string &DataVal);
	//get the DATA value with 'DataName'
	string getData(const string &DataName);


	GDB_Entry getEntry(int number);
	GDB_Entry getEntry(const string &VName, const string &VVal, int index);
	GDB_Entry getEntry(const string &VName1, const string &VVal1, const string &VName2, const string &VVal2, int index);
	//re-set the 'index'-th data entry with new 'VarVal' for given 'VarName'
	void setEntry(int index, const string &VarName, const string &VarVal);
	//add one data entry to the end of current Entries
	void addEntry(const string &VarName, const string &VarVal);


	void addRemark(const string &str); // add one REMARK

	string getResidName(int rNum);
	int getEntryCount(); // return size of current entries

	void presetClass(const string &ClassName); // pre-set the VARS and FORMAT

	bool checkFormat(const string& f); // check if f is a valid FORMAT

	bool isVarFloat(int index);
	bool isVarInt(int index);
	bool isVarString(int index);

	bool isVarFloat(const string &VarName);
	bool isVarInt(const string &VarName);
	bool isVarString(const string &VarName);

	void VARS_str_parser(const string &str);
	void FORMAT_str_parser(const string &str);

	void set_plaintext();


	//strings functions
	static int contains( const string &str, const string &c );
	static int contains( const string &str, const char &c );
	//
	
	static bool isDigit( const char &c );
	static bool isSpace( const char &c );
	
	static StringList split( const char &sep, const string &str );
	static StringList split( const string &sep, const string &str );
	//splits the string str into strings wherever a separator 'sep' occurs, and returns the list of those strings.
	
	static char * section( const string &str, const char &seq, char *buff, int start, int end= 0xffffffff );
	//returns a section of the string, each section is defined by char 'sep', numbers of start and end are the index number (begin with 0)

	static string simplifyWhiteSpace( const string &str );
	//Returns a string that has whitespace removed from the start and the end, 
	//and which has each sequence of internal whitespace replaced with a single space.
};

#endif
