/* base int main() */
#include <sys/types.h>
#include <boost/lambda/lambda.hpp>
#include <iterator>
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <errno.h>
#include <stdlib.h>

#include "BoostImplement.h"
#include "BufferRetive.h"
#include "RetiveData.h"
#include "stdafx.h"

#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <db_cxx.h>
#include <cstdlib>
#include <fstream>

//ACE 
#include "CSDWalker.h"

#ifdef _WIN32
extern "C" {
  extern int getopt(int, char * const *, const char *);
  extern char *optarg;
}
#else
#include <unistd.h>
#endif

/* include environtmenCreate class */


using std::ostream;
using std::cout;
using std::cerr;

//forward declarations
int show_item(EnvironmentCreate &itemnameSDB,EnvironmentCreate &vendorDB, std::string &itemName);
int show_vendor(EnvironmentCreate &vendorDB,const char *vendor);

/*constructors  for create path and database name */
EnvironmentCreate::EnvironmentCreate( std::string& pathCreate,
		std::string& databaseName,
		const char *valuePrograms_ ,
		bool isSecondary )
		:pathDbFileName_( pathCreate+databaseName ),
		programs_( valuePrograms_ ),
		databaseDBObject_(NULL,0),
		keySet_(NULL,0),
		valueSet_(NULL,0),
		cFlags_( DB_CREATE )
		{
				/*exception for handle open database*/
			try
			{
				/*error database,check help handle database support */
				databaseDBObject_.set_error_stream( &std::cerr );
				
				/*sort deuplicates,if this is a secondary database*/
				if( isSecondary )
				{
					databaseDBObject_.set_flags( DB_DUPSORT );
				}
				
			/*open database*/
				databaseDBObject_.open( NULL, pathDbFileName_.c_str( ), NULL, DB_BTREE, cFlags_, 0 );
				
				
				
			}
			catch( DbException &exception )
			{ 
				std::cout<<"-------------------------------------------------"<<"\n";
				std::cout<<"Error open database Environment "<<pathDbFileName_<<"\n";
				std::cerr<<exception.what()<<std::endl;
				std::cout<<"-------------------------------------------------"<<"\n";
			}
			catch( std::exception &exception )
			{
				std::cout<<"-------------------------------------------------"<<"\n";
				std::cout<<"Error open database Environment "<<pathDbFileName_<<"\n";
				std::cerr<<exception.what()<<std::endl;
				std::cout<<"-------------------------------------------------"<<"\n";
			}
	      
	
	    };
		
/* constructor */
		EnvironmentCreate::EnvironmentCreate()
										:databaseDBObject_(NULL,0),
										keySet_(NULL,0),
										valueSet_(NULL,0){};
		
/* close database memberfion define */
		void EnvironmentCreate::close()
		{
			//handle close database;
			try
			{
				std::cout<<"-------------------------------------------------"<<"\n";
				databaseDBObject_.close( 0 );
				std::cout<<"Database close "<< databaseName_ <<"\n";
				std::cout<<" closed() "<<std::endl;
				std::cout<<"-------------------------------------------------"<<"\n";
			}
			catch( DbException &dbHandle )
			{
				std::cout<<"-------------------------------------------------"<<"\n";
				std::cerr<<" Error closing database "<< databaseName_ <<"\n";
				std::cerr<< dbHandle.what() <<std::endl;
				std::cout<<"-------------------------------------------------"<<"\n";
			}
			catch( std::exception &exception )
			{
				std::cout<<"-------------------------------------------------"<<"\n";
			     std::cout<<"Error closing databse "<<pathDbFileName_<<"\n";
				 std::cerr<<exception.what()<<std::endl;
				 std::cout<<"-------------------------------------------------"<<"\n";
			}
		}
		
    /* define insertDatabase
     * return ture,if can insert data */
		bool EnvironmentCreate::insertDatabase(char *keyInsert,
			char *valueInsert,
			const EnvironmentCreate& environmentDatabasePathName )		
		   {
			/*for handle insert data to database file */
			try
			{

				/*set path name */
				std::string pathSetOpen = environmentDatabasePathName.pathDbFileName_;		
				std::cout<<"Print path name : "<<pathSetOpen<<std::endl; 

				databaseDBObject_.open( NULL, pathDbFileName_.c_str( ), NULL, DB_BTREE, cFlags_, 0 );
				
				/* Error checking */
				databaseDBObject_.set_errpfx( " Error on insertDatabase data member \n" );				
				/*
				 * author Chatsiri.rat
				 *
				 * set key value length 
				 */
				u_int32_t  key_len = ( u_int32_t )strlen( keyInsert );
				
				/*
				 * author Chatsiri.rat
				 *
				 * set data value length
				 */
				 u_int32_t value_len = ( u_int32_t )strlen( valueInsert );
				 /*
				 * author Chatsiri.rat
				 *  Dbt for set key and value
				 */
				 Dbt keySet_( keyInsert, key_len + 1 );
				//setDbt( &keyInsert, key_len ); 
				
				 Dbt valueSet_( valueInsert, value_len + 1 );
				 
				 /*
				 * author Chatsiri.rat
				 *  variable for check error key exist 
				 */
				 int ret = databaseDBObject_.put( 0, & keySet_ , &valueSet_, DB_NOOVERWRITE );
				 
				 if( ret = DB_KEYEXIST )
				 {
					 databaseDBObject_.err( ret, " " );
				 }
				 
				 /*
				 * author Chatsiri.rat
				 * Store value 
				 */
				 Dbt storeValue_;
				 ret = databaseDBObject_.get( 0, &keySet_, &storeValue_, 0 );
				 std::cout<<"StroeValue_ : "<<( char * )storeValue_.get_data()<<std::endl;
				 databaseDBObject_.close(0);			
				return true;
			}
			catch( DbException &dbex )
			{
				std::cout<<"------------------------------------------------------"<<std::endl;
				databaseDBObject_.err( dbex.get_errno(), "DB exception caught (insertDatabase)\n" );
				std::cout<<"------------------------------------------------------"<<std::endl;
				return false;
			}
		}
		





int _tmain(int argc, _TCHAR* argv[])
{


    
	std::string valuePath = "c:/tmp/database/";
	std::string valueDBName = "filename_" ;
	std::string itemnameSDB = "itemname.sdb";
    const char *_valueProgramsSet = "programsDatabase";
	//MyDb myDbCreate( valuePath, valueDBName, false );
    EnvironmentCreate myDbCreate( valuePath, valueDBName, _valueProgramsSet, false );  
     char *_valueKey  = "keyData1";
	 char *_valueData = "Chatsiri.rat";
	 std::string valueShow("keyData1");
	EnvironmentCreate myDbInsert2;
	//insert data 
	myDbInsert2.insertDatabase( _valueKey, _valueData,  myDbCreate);
	
	

	//create path for read database file
	std::string databaseHome("./");
	std::string itemName("c:/tmp/database/");

	std::string valueDatabase("filename");

	try{

		EnvironmentCreate buffVendor( databaseHome, valueDBName, _valueProgramsSet);
		
		EnvironmentCreate buffRetiveSDB( databaseHome, itemnameSDB, _valueProgramsSet,true);

		//Associate secondrary to the primary
		buffVendor.getDb().associate(NULL,
			&(buffRetiveSDB.getDb()),
			get_item_name,
			0);
		
		show_item( buffRetiveSDB, buffVendor, valueShow  );
		show_vendor( buffVendor, _valueKey );
	}
	catch(DbException &e)
	{
		std::cerr<<"Error read database "<<std::endl;
		return ( e.get_errno() );
	}
	catch(std::exception &e)
	{
		std::cerr<<e.what()<<std::endl;
		return (-1);
	}

		
		



//	boostImpelementScoped_str();

//	stlTestPair();

//	iterPari();





	

}


/*set for show value */
int show_item(EnvironmentCreate &itemnameSDB,
			  EnvironmentCreate &vendorDB,
			  std::string &itemName )
{
	//create cursor
	Dbc *cursorPointer;

	try{
		itemnameSDB.getDb().cursor( NULL, &cursorPointer, 0 );

		std::cout<<"Look for "<< itemName<<std::endl;
		Dbt key( (void*)itemName.c_str(), (u_int32_t)itemName.length() + 1 );
		Dbt data;
		//return 0 value if it have data
		int ret  = cursorPointer->get(&key,&data,DB_SET);
if( !ret ) 
{
	do
	{
		BufferRetive bufferRet(data.get_data());
		bufferRet.show();


	}while( cursorPointer->get(&key, &data, DB_SET ) == 0 );
}
else
{
	std::cerr<<"Not record : "<<itemName<<std::endl;

}
	}
	catch(DbException &e )
	{
		itemnameSDB.getDb().err( e.get_errno(), "Error in show_item ");
		cursorPointer->close();
		throw e;	
	}
	catch(std::exception &e )
	{
		itemnameSDB.getDb().errx(" Erorr is show_item %s",e.what());
		cursorPointer->close();
		throw e;
	}
	cursorPointer->close();
	return (0);
}








int show_vendor(EnvironmentCreate &vendorDB,const char *vendor )
{
	Dbt data;
	VENDOR my_vendorStruct;
	try
	{
		Dbt key((char *)vendor, (u_int32_t)strlen(vendor) + 1 );

		data.set_data(&my_vendorStruct);
		data.set_ulen(sizeof(VENDOR));
		data.set_flags(DB_DBT_USERMEM);

		vendorDB.getDb().get(NULL,&key,&data,0);

		std::cout<<" "<<my_vendorStruct.name<< "  "<<std::endl;
	}
	catch(DbException &e)
	{
		vendorDB.getDb().err(e.get_errno(),"Error show vendor " );
		throw e;
	}
	catch(std::exception &e)
	{
		throw e;
	}
	return (0);
}



