#include <fstream>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <list>
#include <utility>
#include "memorydatabase.hpp"

using namespace std;

void error_return(const char* msg)
{
	cerr << msg;
	exit(3);
}

class mystring
{
public:
	string my;

	mystring() {}
	mystring(const string& s) : my(s) {}

	istream& read(istream& is)
	{
		size_t t;
		char *nstr;

		is.read(&t, sizeof(t));
		nstr = new char[t];
		is.read(nstr,t);
		my = string(nstr);

		delete [] nstr;
	}

	ostream& write(ostream& os)
	{
		size_t t;

		t = my.length() + 1;

		os.write(&t,sizeof(t));
		os.write(my.c_str(),t);
	}
};

int main(int argc, char *argv[])
{
	int i;
	ID id;
	list<ID> m;
	list<ID>::iterator p;
	MemoryDatabase<mystring> ms;
	MemoryDatabase<mystring> ps;
	pair<mystring,bool> ret;
	mystring s;
	fstream outfile;
	fstream infile;

	ms.Create("Hello");
	for(i=argc-1; i > 0; i--) 
	{
		s = string(argv[i]);
		id = ms.Add(s);

		cout << "ID: " << id << "	";
		cout << "DATA: " << s.my << endl;

		m.push_back(id);
	}

	for(p = m.begin(); p != m.end(); p++)
	{
		ret = ms[*p];

		if(!ret.second) 
			cout << "Couldn't retrieve the record from the database" << endl;
		else
		{
			cout << "ID " << *p << "	";
			cout << "string " << ret.first.my << endl;
		}
	}

	cout << endl << "Here we delete all" << endl;

	ms.RemoveAll();

	for(p = m.begin(); p != m.end(); p++)
	{
		ret = ms[*p];

		if(!ret.second) 
			cout << "Couldn't retrieve the record from the database" << endl;
		else
		{
			cout << "ID " << *p << "	";
			cout << "string " << ret.first.my << endl;
		}
	}	
	m.clear();

	cout << endl << "Here we read them all again" << endl;

	for(i=argc-1; i > 0; i--) 
	{
		s = string(argv[i]);
		id = ms.Add(s);

		cout << "ID: " << id << "	";
		cout << "DATA: " << s.my << endl;

		m.push_back(id);
	}

	for(p = m.begin(); p != m.end(); p++)
	{
		ret = ms[*p];

		if(!ret.second) 
			cout << "Couldn't retrieve the record from the database" << endl;
		else
		{
			cout << "ID " << *p << "	";
			cout << "string " << ret.first.my << endl;
		}
	}	

	cout << endl << "ANd the second time" << endl;

	for(i=argc-1; i > 0; i--) 
	{
		s = string(argv[i]);
		id = ms.Add(s);

		cout << "ID: " << id << "	";
		cout << "DATA: " << s.my << endl;

		m.push_back(id);
	}

	for(p = m.begin(); p != m.end(); p++)
	{
		ret = ms[*p];

		if(!ret.second) 
			cout << "Couldn't retrieve the record from the database" << endl;
		else
		{
			cout << "ID " << *p << "	";
			cout << "string " << ret.first.my << endl;
		}
	}	

	cout << endl << "Here we delete all the second time" << endl;

	p = m.begin();
	for(; p != m.end(); p++) ms.Remove(*p);

	for(p = m.begin(); p != m.end(); p++)
	{
		ret = ms[*p];

		if(!ret.second) 
			cout << "Couldn't retrieve the record from the database" << endl;
		else
		{
			cout << "ID " << *p << "	";
			cout << "string " << ret.first.my << endl;
		}
	}	

	m.clear();
	
	cout << endl << "Here we read them all again" << endl;

	for(i=argc-1; i > 0; i--) 
	{
		s = string(argv[i]);
		id = ms.Add(s);

		cout << "ID: " << id << "	";
		cout << "DATA: " << s.my << endl;

		m.push_back(id);
	}

	for(p = m.begin(); p != m.end(); p++)
	{
		ret = ms[*p];

		if(!ret.second) 
			cout << "Couldn't retrieve the record from the database" << endl;
		else
		{
			cout << "ID " << *p << "	";
			cout << "string " << ret.first.my << endl;
		}
	}

	cout << endl << "Here we write and read" << endl;

	outfile.open("/h/11/trokhim/work/code/mdtest.dat", ios::out | ios::binary);
	cout << "hey1" << endl;
	if(!outfile) error_return("Couldn't open output file");
	cout << "hey2" << endl;

	ms.Write(outfile);
	cout << "hey3" << endl;
	if(!outfile) error_return("couldn't write to the output file");
	cout << "hey3.1" << endl;

	outfile.close();
	cout << "hey4" << endl;

	infile.open("/h/11/trokhim/work/code/mdtest.dat", ios::in | ios::nocreate | ios::binary);

	if(!infile) error_return("Couldn't open input file");
	cout << "hey5" << endl;

	ps.Read(infile);
	cout << "hey6" << endl;
	if(!infile) error_return("couldn't read from input file");

	cout << "hey7" << endl;
	infile.close();
	cout << "hey8" << endl;

	for(p = m.begin(); p != m.end(); p++)
	{
		ret = ps[*p];

		if(!ret.second) 
			cout << "Couldn't retrieve the record from the database" << endl;
		else
		{
			cout << "ID " << *p << "	";
			cout << "string " << ret.first.my << endl;
		}
	}

	return 0;
}