//#include "dbmail.h"
#include <stdio.h>
#include <sys/types.h>
#include <glib.h>
#include <pthread.h>
#include <libmemcached/memcached.h>
#include "dm_memcache.h"

#define MEMCACHE "Y"
#define MC_SERVER1 "127.0.0.1"
#define MEMCACHE_PRFX "dbm"
#define KEY_SIZE 20
#define MAX_VALUE 1024
#define VALUE_SIZE 1024
#define KEY_BUFFER

char *keybuffer[], *valuesbuffer[], *returnbuffer[], *bufferaction;
int glock=1,*bufferelements;


int chkmc(){
	if(MEMCACHE == "Y" || MEMCACHE == "y" || MEMCACHE == "yes" || MEMCACHE == "YES")
		return 1;
	else
		return 0;
}
char* construct_keyname(char *key, char *postfix){
        char *keyname;
        keyname = g_new0(char,KEY_SIZE); //allocate memory that is freed inmemcache_gstr and memcache_gid

        snprintf(keyname,
                KEY_SIZE,
                "%s%s_%s",
                MEMCACHE_PRFX,
                key,
                postfix);

        return keyname;
}

char *memcache_gstr(char *key, int id){
        char *ret, *keyname, keyid[4];
	ret = g_new0(char,VALUE_SIZE);
	keyname = g_new0(char,KEY_SIZE);
	memset(keyid, 0, sizeof(keyid));

        sprintf(keyid,"%d",id);
        keyname= construct_keyname(key,keyid);
        printf("key: %s\n", keyname);
	ret = memcache_get(keyname);
        free(keyname);
        return ret;
}

void memcache_sstr(char *key, int id,char*value){
        char keyid[4];
	memset(keyid, 0, sizeof(keyid));

        sprintf(keyid,"%d",id);
        key = construct_keyname(key,keyid);
        printf("sstr: %s,%d,%s\n",key,id,value);
        memcache_set(key,value);
        free(key);
}
int memcache_gint(char*key,char*postfix){
	char *keyuser, *ret;
        int *ret64u;
	keyuser = g_new0(char,KEY_SIZE);
	ret = g_new0(char,VALUE_SIZE);
	ret64u = g_new0(int,4);

        keyuser = construct_keyname(key,postfix);
        ret = memcache_get(keyuser);
        free(keyuser);
        if(ret != NULL)
                ret64u = atoi(ret);
        return ret64u;

}

void memcache_sint(char*key, int id,char*value){
//	char *keyuser;
	//char *value;
//	value = (char *)malloc(MAX_VALUE*sizeof(char));
//	sprintf(value,"%d",id);
//	keyuser = construct_keyname(key,
}

int *memcache_gid(char*username){
	char *keyuser, *ret;
        int *ret64u;
	keyuser=g_new0(char,KEY_SIZE);
	ret=g_new0(char,VALUE_SIZE);
	ret64u=g_new(int,4);

        keyuser = construct_keyname("idnr",username);
        ret = memcache_get(keyuser);
        free(keyuser);
        if(ret != NULL)
                ret64u = atoi(ret);
        return ret64u;
}

void memcache_sid(char*username, int id){
	char *keyuser, *value;
	keyuser=g_new0(char,KEY_SIZE);
	value=g_new0(char,VALUE_SIZE);
	sprintf(value,"%d",id);
	keyuser = construct_keyname("idnr",username);
	memcache_set(keyuser,value);
	free(keyuser);	
}
int *memcache_intreturn(char*string){
	return atoi(string);
}

char *memcache_charreturn(long int *number){
	char *buffer;
	buffer = g_new0(char,VALUE_SIZE);
	snprintf(buffer,"%d",number);
	return buffer;
}

char *memcache_gencode(int id){
        return memcache_gstr("encode",id);
}
long int memcache_gmaxmail(int id){
	return strtol(memcache_gstr("maxmail",id),NULL,0);
}

long int memcache_gcurmail(int id){
	return strtol(memcache_gstr("curmail",id),NULL,0);
}

long int *memcache_gmaxseive(int id){
	return strtol(memcache_gstr("maxseive",id),NULL,0);
}

void memcache_smaxmail(int id, long int *value){
	memcache_sstr("maxmail",id,memcache_charreturn(value));
}

void memcache_sencode(int id,char *value){
        memcache_sstr("encode",id,value);
}
void memcache_scurmail(int id, long int *value){
	memcache_sstr("curmail",id,memcache_charreturn(value));
}
void memcache_sseive(int id, long int *value){
	memcache_sstr("maxseive",id,memcache_charreturn(value));
}

char* memcache_gpasswd(int id){
	return memcache_gstr("passwd",id);
}

void memcache_spasswd(int id,char *value){
	memcache_sstr("passwd",id,value);
}

char * memcache_getmulti(char *keys[], int id, int size){
        memcache_allocate_buffers(size);
	int z;  
        char * keyname;
        char cid[10];

        memset(cid,10,sizeof(cid));

        keyname=g_new0(char,KEY_SIZE);
        bufferelements = size+1;

        for(z=0;z<size;z++){
                sprintf(cid,"%d",id);
                keyname=construct_keyname(keys[z],cid);
                keybuffer[z]=keyname;
        }

        glock =9;
        if(glock == 0)
                sleep(1);
	else
		return returnbuffer;
}

void memcache_setmulti(char *keys[], char *values[], int id, int size){
	memcache_allocate_buffers(size);
	int z;
	char * keyname;
	char cid[10];
	
	memset(cid,10,sizeof(cid));
	
	keyname=g_new0(char,KEY_SIZE);
	bufferelements = size+1;

	for(z=0;z<size;z++){
		sprintf(cid,"%d",id);
		keyname=construct_keyname(keys[z],cid);
		keybuffer[z]=keyname;
		valuesbuffer[z]=values[z];
	}
	
	glock =9;
	if(glock == 0)
		sleep(1);	
	g_free(keyname);
	g_free(cid);
}

void memcache_clear_buffers(){
	g_free(bufferaction);
	g_free(keybuffer);
	g_free(valuesbuffer);
	g_free(returnbuffer);
	g_free(bufferelements);
}

void memcache_allocate_buffers(int size){
	*keybuffer = (char *)malloc(size * sizeof(char *));	
	*valuesbuffer = (char *)malloc(size * sizeof(char *));
	*returnbuffer = (char *)malloc(size  * sizeof(char *));
	bufferelements = malloc(sizeof(int));
	bufferaction = (char *)malloc(sizeof(char*));
}

void memcache_set(char * key, char * value){
	memcache_allocate_buffers(1);
	printf("memcache_set: Allocated buffers\n");
	bufferaction = "set";
	bufferelements = 1;
	//keybuffer=g_new0(char,VALUE_SIZE);
	
	keybuffer[0]=key;
	valuesbuffer[0]=value;

	glock=0;

	if(glock == 0)
		sleep(1);
}

char *memcache_get(char * key){
	memcache_allocate_buffers(1);
	char *ret;
	ret = g_new0(char,VALUE_SIZE);

	bufferaction = "get";

	bufferelements=1;
	keybuffer[0]=key;
	
	glock=0;
	if(glock == 0){
		sleep(1);
	}else
		ret=valuesbuffer[0];

	return ret;	
}

void thread_process(){
        uint32_t flags;
        size_t return_length;
        char *ret;
	int a;

        ret = g_new0(char,VALUE_SIZE);

        memcached_st * memc = memcached_create(NULL);
        memcached_server_st *servers = NULL;
        memcached_return rc;

        servers= memcached_server_list_append(servers,"localhost",11211, &rc);
        rc= memcached_server_push(memc, servers);

	printf("in thread process\n");
	
	while(1){
		switch(glock){
			case 1: //lock set do sleep
				usleep(1);
				break;
			case 0: //lock cleared process queue
				printf("thread process: processing buffer: action-%s elements-%d\n", bufferaction,bufferelements);
				g_free(returnbuffer);
				*returnbuffer=g_new0(char,VALUE_SIZE);
				for(a=0;a<bufferelements;a++){		        	
					if(strcmp(bufferaction,"get")==0){
						printf("thread process: performing memcache get request: keybuffer-%s\n",keybuffer[a]);

						ret = memcached_get(memc,
        	        	        		keybuffer[a], KEY_SIZE,
                	        			&return_length,
                        				&flags,
                        				&rc);

						returnbuffer[a] = ret;
						g_free(ret);
					}else{
						printf("thread process: performing memcache set request: keybuffer-%s\n",keybuffer[a]);

						rc= memcached_set(memc, 
							keybuffer[a], 
							strlen(keybuffer[a]), 
							valuesbuffer[a],strlen(valuesbuffer[a]), 
							(time_t)0, (uint32_t)0);
					}
				
					if(rc != MEMCACHED_SUCCESS)
                                		fprintf(stderr,"Error: %s\n",memcached_strerror(memc,rc));
				}

           			printf("thread process: setting lock.....\n");
				memcache_clear_buffers();
				glock=1;
				break;
		}
	}
	memcached_free(memc);
		
}


void thread_set(){
	printf("in thread set\n");
	char *buffer;
	char *value;
	char *id;

	buffer = g_new0(char,1024);
	value = g_new0(char,1024);
	id = g_new0(char,1024);

	glock=1;
while(1){
	printf("enter keyname:");
	scanf("%s",buffer);
	printf("enter id:");
	scanf("%s",id);
	printf("enter value:");
	scanf("%s",value);
	if(strcmp(buffer,"x") == 0){
		glock = 9;
		return NULL;
	}
	memcache_spasswd(atoi(id),value);

	//gbuffer=g_new0(char,1024);
	//gbuffer = buffer;
	//printf("setting global buffer %s\n",gbuffer);
	glock = 0;
}
}
void thread_main(){
pthread_t process,set;
pthread_create(&process,NULL,thread_process,NULL);
pthread_create(&set,NULL,thread_set,NULL);
pthread_join(process,NULL);
pthread_join(process,NULL);

}

int main(){
pthread_t pth;
pthread_create(&pth,NULL, thread_main,NULL);
pthread_join(pth,NULL);

return 0;

	if(chkmc()){
	 char *keyencode;
	 int user_idnr = 10;
//	printf("%d \n", (10+sizeof(user_idnr)));
//         snprintf(keyencode,50,"dbmencode_%d",user_idnr);
//	keyencode=construct_keyname("somekey","postfix");
	memcache_sid("skraps",10);
	keyencode = memcache_gid("skraps");
//	printf("%d\n", keyencode);
	memcache_spasswd(10,"pasddsfdsfdsf");
	printf("after setting passwd\n");
	keyencode = memcache_gpasswd(10);
	printf("after getting passwd\n");
	printf("%s\n",keyencode); //memcache_gpasswd(10));

	char *keys[]={"key1","key2","key3","key4"};
	char *values[]={"value1","value2","value3","value4"};
        int y = sizeof(keys)/sizeof(int);
	setmcmulti(keys,values,10,y);
	getmcmulti(keys,10,y);	
	int x = 10;
//	int y = sizeof(keys)/sizeof(int);
	for (x = 0; x < y; x++){
			printf("keys: %s\n",keys[x]);
	}
//	free(keyencode);
//	printf("%s \n", keyencode);
//	printf("%d\n",setmc(keyencode,"some value to cache"));
//	printf("%s\n",getmc(keyencode,50));
	}else{
		printf("MEMCACHE not defined\n");
	}
	return 0;
}

