/**
 * @file   lwdb.c
 * @author mathslinux <riegamaths@gmail.com>
 * @date   Tue May 29 15:24:42 2012
 * 
 * @brief  LWQQ Datebase API
 * We use Sqlite3 in this project
 * 
 * 
 */

#ifndef LWDB_H
#define LWDB_H

#include "type.h"
#include "async.h"
#include "swsqlite.h"

/** return default database store dir */
const char* lwdb_get_config_dir();

//========================= USER DB API =======================================/
#define LWDB_CACHE_LEN 15
typedef struct LwdbUserDB {
	SwsDB *db;
	struct{
		SwsStmt* stmt;
		char* sql;
	}cache[LWDB_CACHE_LEN];
	LwqqBuddy * (*query_buddy_info)(struct LwdbUserDB *db, const char *qqnumber);
	//LwqqErrorCode (*update_buddy_info)(struct LwdbUserDB *db, LwqqBuddy *buddy);
} LwdbUserDB;

/** 
 * Create a user DB object
 * 
 * @param qqnumber : The qq number
 * @param dir      : the database file store directory,NULL to use default path
 * @param flags    : 0
 * 
 * @return A new user DB object, or NULL if somethins wrong
 */
LwdbUserDB *lwdb_userdb_new(const char *qqnumber,const char* dir,int flags);

/** 
 * Free a LwdbUserDB object
 * 
 * @param db 
 */
void lwdb_userdb_free(LwdbUserDB *db);
/**
 * maybe it is better recognisation
 */
#define lwdb_userdb_close(db) (lwdb_userdb_free(db))

/** 
 * insert a buddy info to database
 * if there is no database entry, create one and update it
 * @param p_buddy <- a pointer to LwqqBuddy* . compable with LwqqEvents
 */
LwqqErrorCode lwdb_userdb_insert_buddy_info(LwdbUserDB* db,LwqqBuddy** p_buddy);
/** 
 * insert a group info to database
 * if there is no database entry, create one and update it
 * @param p_group <- a pointer to LwqqGroup* . compable with LwqqEvents
 */
LwqqErrorCode lwdb_userdb_insert_group_info(LwdbUserDB* db,LwqqGroup** p_group);
#define lwdb_userdb_insert_discu_info(db,discu) lwdb_userdb_insert_group_info(db,discu)

/** 
 * update a buddy info to database
 * if there is no database entry, error occurs
 * @param p_buddy <- a pointer to LwqqBuddy* . compable with LwqqEvents
 */
LwqqErrorCode lwdb_userdb_update_buddy_info(LwdbUserDB* db,LwqqBuddy** p_buddy);
/** 
 * update a group info to database
 * if there is no database entry, error occurs
 * @param p_group <- a pointer to LwqqGroup* . compable with LwqqEvents
 */
LwqqErrorCode lwdb_userdb_update_group_info(LwdbUserDB* db,LwqqGroup** p_group);
#define lwdb_userdb_update_discu_info(db,discu) lwdb_userdb_update_group_info(db,discu)

/** erase infomation older than @day and at most @last entries , 
 * when query buddy, LwqqBuddy::last_modify puts LWQQ_LAST_MODIFY_RESET
 */
void lwdb_userdb_flush_buddies(LwdbUserDB* db,int last,int day);
/** erase infomation older than @day and at most @last entries , 
 * when query group, LwqqGroup::last_modify puts LWQQ_LAST_MODIFY_RESET
 */
void lwdb_userdb_flush_groups(LwdbUserDB* db,int last,int day);
/**
 * query all buddies and groups qqnumber from database
 */
void lwdb_userdb_query_qqnumbers(LwdbUserDB* db,LwqqClient* lc);
/** 
 * get data from database, only be sure buddy has qqnumber already 
 */
LwqqErrorCode lwdb_userdb_query_buddy(LwdbUserDB* db,LwqqBuddy* buddy);
/** 
 * get data from database, only be sure group has qqnumber already 
 */
LwqqErrorCode lwdb_userdb_query_group(LwdbUserDB* db,LwqqGroup* group);

/** begin a transaction*/
void lwdb_userdb_begin(LwdbUserDB* db);
/** end a transaction*/
void lwdb_userdb_commit(LwdbUserDB* db);
/** read a custom key in database */
const char* lwdb_userdb_read(LwdbUserDB* db,const char* key);
/** write a custom key,value in database */
int lwdb_userdb_write(LwdbUserDB* db,const char* key,const char* value);
/* LwdbUserDB API end */

LwqqExtension* lwdb_make_extension(LwdbUserDB* db);

/************************************************************************/
/* Initialization and final API */
/** 
 * LWDB initialization
 * 
 */
void lwdb_global_free();

/** 
 * LWDB final
 * 
 */
void lwdb_finalize();

/* Initialization and final API end */

/************************************************************************/
/* LwdbGlobalDB API */
typedef struct LwdbGlobalUserEntry {
	char *qqnumber;
	char *db_name;
	char *password;
	char *status;
	char *rempwd;
	LIST_ENTRY(LwdbGlobalUserEntry) entries;
} LwdbGlobalUserEntry;

typedef struct LwdbGlobalDB {
	SwsDB *db;                  /**< Pointer sqlite3 db */
	LwqqErrorCode (*add_new_user)(struct LwdbGlobalDB *db, const char *qqnumber);
	LwdbGlobalUserEntry * (*query_user_info)(struct LwdbGlobalDB *db,
			const char *qqnumber);
	LIST_HEAD(, LwdbGlobalUserEntry) head; /**< QQ friends */
	LwqqErrorCode (*update_user_info)(struct LwdbGlobalDB *db, const char *qqnumber,
			const char *key, const char *value);
} LwdbGlobalDB;

/** 
 * Create a global DB object
 * 
 * @return A new global DB object, or NULL if somethins wrong, and store
 * error code in err
 */
LwdbGlobalDB *lwdb_globaldb_new(void);

/** 
 * Free a LwdbGlobalDb object
 * 
 * @param db 
 */
void lwdb_globaldb_free(LwdbGlobalDB *db);

/** 
 * Free LwdbGlobalUserEntry object
 * 
 * @param e 
 */
void lwdb_globaldb_free_user_entry(LwdbGlobalUserEntry *e);

/* LwdbGlobalDB API end */

/************************************************************************/
/* LwdbUserDB API */



/************************************************************************/
#if 0
void lwdb_userdb_write_to_client(LwdbUserDB* from,LwqqClient* to);
void lwdb_userdb_read_from_client(LwqqClient* from,LwdbUserDB* to);
#endif

#endif

// vim: ts=3 sw=3 sts=3 noet
