#include "disk_tools.h"
#include "d_list.h"
#include "d_vector.h"
#include "d_hashmap.h"
#include "d_ptr.h"
#include "d_var.h"
#include "d_ref.h"
#include "d_map.h"
#include <cstring>
#include <algorithm>
#include <limits.h>

using namespace std;
using namespace disk_tools;

/*
int
str_compare(DB * db, const DBT * pk1, const DBT * pk2)
{
   int ret = 0;
   string a1 = (char*)pk1->data;
   string a2 = (char*)pk2->data;
   if(a1 < a2) ret = -1;
   else if(a1 > a2) ret = 1;
   else ret = 0;
   return ret;
}
*/


class string_hash {
public:
   offset_type operator()(const string & str) const {
      offset_type sum = 0L;
      for(size_t i = 0; i < str.size(); i++) {
         sum += str[i] * i;
      }
      return LONG_MAX - sum;
   }
};

int
main(int argc, char ** argv)
{
   bool init = false;
 
   for(int i = 0; i < argc; i++) {
      if(strcmp(argv[i], "-init") == 0) {
         init = true;
      }
   }

   try {
      d_env env;

      p_d_env = & env;

      if(init) {
         create_database("test");
         d_database * db = open_database("test");
         {
            d_map< d_ref< string >, d_ref< string >, string > bt("bt");
         }
         close_database(db);
         exit(0);
      }

cout << "open db next..." << endl;

      d_database * db = open_database("test");

cout << "db open..." << endl;

      d_list< string > the_list("the_list");

cout << "list open..." << endl;

      the_list.push_front("HATE");
cout << "did push 1" << endl;
      the_list.push_front("HATE");
cout << "did push 2" << endl;
      the_list.push_front("HATE");
      the_list.push_back("LOVE");
      the_list.push_back("LOVE");
      the_list.push_back("LOVE");
cout << "did push..." << endl;
      for(d_list< string >::iterator ptr = the_list.begin(); ptr != the_list.end(); ptr++) {
         cout << "DATA = " << (string)(*ptr) << endl; 
      }

cout << "did list..." << endl;

      the_list.pop_front();
cout << "did pop 1" << endl;

      the_list.pop_back();

cout << "did pop 2" << endl;

      d_list< string >::iterator ptr = the_list.begin();

cout << "iterator..." << endl;

      ptr++;
      ptr++;
      ptr++;
      the_list.insert(ptr, "GOD");

      ptr = the_list.begin();
      ptr++;
      the_list.erase(ptr);

      ptr = the_list.begin();
      ptr++;
      *ptr = "<<GOD>>";

cout << "sort.." << endl;
      the_list.sort();
cout << "did sort..." << endl;

      for(d_list< string >::iterator ptr = the_list.begin(); ptr != the_list.end(); ptr++) {
         cout << "DATA = " << (string)(*ptr) << endl; 
      }

      cout << "done with stirng list..." << endl;

      d_list< d_list< int > > ll("ll");

      d_list< int > il;

      cout << "made the lists..." << endl;

      il.push_back(1);
      il.push_back(2);
      il.push_back(3);
      il.sort();

      ll.push_back(il);

      for(d_list< int >::iterator ptr2 = il.begin(); ptr2 != il.end(); ptr2++) {
         cout << "int=" << ((int)(*ptr2)) << endl;
      }

      for(d_list< d_list< int > >::iterator ptr1 = ll.begin(); ptr1 != ll.end(); ptr1++) {
         cout << "---" << endl;
         for(d_list< int >::iterator ptr2 = ptr1->begin(); ptr2 != ptr1->end(); ptr2++) {
            cout << "ptr2 == " << *ptr2 << endl;
         }
      }

      offset_type n = 1000;

      offset_type addr;

      d_hashmap< string, string, string_hash > htable("htable");

      string temp;


      cout << "--------------------------------------" << endl;

      htable["hello"] = "HELLO" + (string)htable["hello"];
      htable["world"] = "WORLD" + (string)htable["world"];
      htable["matthew"] = "MATTHEW" + (string)htable["matthew"]; 
      htable["hello2"] = "HELLO2" + (string)htable["hello2"];
      htable["love"] = "LOVE" + (string)htable["love"];

      cout << "--------------------------------------" << endl;

      cout << "hello=" << htable["hello"] << endl;
      cout << "world=" << htable["world"] << endl;
      cout << "matthew=" << htable["matthew"] << endl;
      cout << "hello2=" << htable["hello2"] << endl;
      cout << "love=" << htable["love"] << endl;

      //htable.erase("love");

      d_vector< string > str_vec("str_vec", 100);
  
      str_vec.push_back("AA");
      str_vec.push_back("BB");
      str_vec.push_back("CC");

      d_vector< string >::iterator ptr0;

      ptr0 = str_vec.begin(); 
      str_vec.insert(ptr0, "PP");

      str_vec[0] = (string)str_vec[0] + "Z";

      ptr0 = str_vec.begin(); 
      ptr0++;
      str_vec.insert(ptr0, "GG");

      str_vec.sort();
      //sort(str_vec.begin(), str_vec.end());

      for(offset_type i = 0L; i < str_vec.size(); i++) {
         cout << "str_vec[" << i << "] == " << (string)str_vec[i] << endl;
      }

      addr = create_pointer(db);
      d_ptr< string > str_ptr(addr);
      *str_ptr = "HELLO, WORLD!";
      cout << (string)*str_ptr << endl;

      d_var< string > var;
      var = "I love C++!";
      cout << (string)var << endl; 
      str_ptr = &var;
      cout << (string)*str_ptr << endl;

      d_var< string > var2("var2");
      cout << "HELLO: " << (string)var2 << endl; 
      var2 = "Matthew";
      cout << "HELLO: " << (string)var2 << endl; 

      {

      d_map< d_ref< string >, d_ref< string >, string > bt("bt");

      bt[string("love")] = string("LOVE") + (string)(bt[string("love")]);
      bt[string("hello")] = string("HELLO") + (string)(bt[string("hello")]);
      bt[string("god")] = string("GOD") + (string)(bt[string("god")]);

      cout << "love=" << (string)(bt[string("love")]) << endl;
      cout << "hello=" << (string)(bt[string("hello")]) << endl;
      cout << "god=" << (string)(bt[string("god")]) << endl;

      for(d_map< d_ref< string >, d_ref< string >, string >::iterator ptr = bt.begin(); ptr != bt.end(); ptr++) {
         cout << (string)(ptr->first) << "=" << (string)(ptr->second) << endl;
      }

      }

      close_database(db);

      cout << "done..." << endl;
   }
   catch(const char * message) {
      cerr << message << endl;
   }
   catch(...) {
      cerr << "..." << endl;
   }

   return 0;
}
