/* the cfg.db routines are basically for storing history information --
 * i.e., the settings default to the last settings used, a command
 * history is stored, and so on. This is not intended to be a user-set
 * configuration file. */
#include <bastard.h>
#include <db/db_main.h>
#include <config.h>
#include <extension.h>
#include <debug.h>

extern struct DISASM_TGT target;
extern struct DISASM_ENV disasm_env;
extern struct DISASM_PREFS disasm_prefs;


int LoadConfigDB(char *name){
   char default_cfg[1024];
   int db_id;

   if (! name ) {
      name = default_cfg;
      snprintf(default_cfg, 1024, "%s/config.bdb", disasm_env.dbpath);
   } 
   strncpy( db_config->name, "cfg", 64);
   strncpy( db_config->filename, name, 256);

   db_id = LoadDB(db_config->name, name, db_config);
   return(db_id);
}

int UnloadConfigDB(){
   char name[256], cmdBuf[256], pwd[PATH_MAX];
   FILE *tmp;
   int rv;


   /* load saved name */
   if (! disasm_env.dbpath[0]) strcpy(disasm_env.dbpath, ".");
   getcwd(pwd, PATH_MAX);
   chdir(disasm_env.dbpath);
      
   sprintf(cmdBuf, "tar --remove-files -zcf %s .config.bdb", 
         db_config->filename);
   DEBUG_PrintVar(cmdBuf, "%s");
   if(!((tmp=popen(cmdBuf, "r")) && (pclose(tmp)==0))) {
      unlink(db_config->filename);
      ErrorMsg(4565, "Unable to save config .bdb!");
      SetLastError(4565);
      rv = 0;
   }
   chdir(pwd);

   rv = UnloadDB( db_config );

   sprintf(cmdBuf, "rm -rf %s/.config.bdb", disasm_env.dbpath);
   DEBUG_PrintVar(cmdBuf, "%s");
      if(!((tmp=popen(cmdBuf, "r")) && (pclose(tmp)==0))) {
      ErrorMsg(4511, "Error cleaning up .bdb");
      rv = 0;
   }

   return(rv);
}

/* insert profile struct into DB */
int CreateProfile(int table, void *data){
   int db_id, rv;

   db_id = SwitchDB(db_config->db_id);
   /* blindly insert data into table :) */
   rv = d_fillnew(table, data);
   SwitchDB(db_id);
   return(rv);
}

/* write profile struct to DB */
int UpdateProfile(int table, void *id){
   int index, rv, db_id;
   void *data; /* pointer to whatever data struct is required */
   struct profile_env env;
   struct profile_pref pref;
   struct profile_asm asmblr;
   struct profile_arch arch;
   struct profile_target tgt;
   
   /* switch based on table (profile type) */
   switch (table){
      case PROFILE_ENV:
         index = PROFILE_ENV_USER;
         data = &env;
         strncpy(env.user, id, 32);
         strncpy(env.home, disasm_env.home, 256);
         strncpy(env.p1, disasm_env.p1, 16);
         strncpy(env.p2, disasm_env.p2, 16);
         strncpy(env.p3, disasm_env.p3, 16);
         strncpy(env.p4, disasm_env.p4, 16);
         strncpy(env.dbpath, disasm_env.dbpath, 256);
         env.output = disasm_env.output;
         break;
      case PROFILE_PREF:
         index = PROFILE_PREF_USER;
         data = &pref;
         strncpy(pref.user, id, 32);
         strncpy(pref.arch, strrchr(ext_arch->ext.filename, '/') + 1, 32);
         strncpy(pref.asmblr, strrchr(ext_asm->ext.filename, '/') + 1, 32);
         strncpy(pref.format, strrchr(ext_format->ext.filename, '/') + 1, 32);
         strncpy(pref.lang,  strrchr(ext_lang->ext.filename, '/') + 1, 32);
         strncpy(pref.pager, disasm_prefs.pager, 256);
         strncpy(pref.editor, disasm_prefs.editor, 256);
         strncpy(pref.debugger, disasm_prefs.debugger, 256);
         pref.options = disasm_prefs.options;
         break;
      case PROFILE_ASM:
         index = PROFILE_ASM_NAME;
         data = &asmblr;
         strncpy(asmblr.name, id, 32);
         strncpy(asmblr.asm_ttyColor, ext_asm->asm_ttyColor, 128);
         strncpy(asmblr.data_ttyColor, ext_asm->data_ttyColor, 128);
         strncpy(asmblr.asm_ttyMono, ext_asm->asm_ttyMono, 128);
         strncpy(asmblr.data_ttyMono, ext_asm->data_ttyMono, 128);
         strncpy(asmblr.asm_file, ext_asm->asm_file, 128);
         strncpy(asmblr.data_file, ext_asm->data_file, 128);
         strncpy(asmblr.asm_lpr, ext_asm->asm_lpr, 128);
         strncpy(asmblr.data_lpr, ext_asm->data_lpr, 128);
         break;
      case PROFILE_ARCH:
         index = PROFILE_ARCH_NAME;
         data = &arch;
         strncpy(arch.name, id, 32);;
         arch.options = ext_arch->options;;
         break;
      case PROFILE_TARGET:
         index = PROFILE_TARGET_NAME;
         data = &tgt;
         strncpy(tgt.name, id, 256);
         strncpy(tgt.path, target.path, 256);
         strncpy(tgt.dbname, target.dbname, 256);
         tgt.size = target.size;
         tgt.entry = target.entry;
         strncpy(tgt.arch, target.arch, 32);
         //strncpy(tgt.asmblr, target.asm, 32);
         strncpy(tgt.format, target.format, 32);
         strncpy(tgt.lang, target.lang, 32);
         break;
   }
   db_id = SwitchDB(db_config->db_id);
   /* if profile exists, update the record */
   if ( d_keyfind(index, id) == S_OKAY){
      rv = d_recwrite(data);
   } else {
   /* else create it */
      rv = CreateProfile( table, data);
   }
   SwitchDB(db_id);
   return(rv);
}

/* Get profile in DB into struct */
int GetProfile(int table, void *id, void *dest){
   int index, db_id, rv = 1;

   switch (table) {
      case PROFILE_ENV:
         index = PROFILE_ENV_USER;
         break;
      case PROFILE_PREF:
         index = PROFILE_PREF_USER;
         break;
      case PROFILE_ASM:
         index = PROFILE_ASM_NAME;
         break;
      case PROFILE_ARCH:
         index = PROFILE_ARCH_NAME;
         break;
      case PROFILE_TARGET:
         index = PROFILE_TARGET_NAME;
         break;
   }
   db_id = SwitchDB(db_config->db_id);
   if (d_keyfind(index, id) == S_OKAY){
      d_recread(dest);
   }
   else {
      rv = 0;
   }
      
   SwitchDB(db_id);
   return(rv);
}

/* Get Profile and Apply it to current ENV */
LoadProfile(int table, void *id){
   struct profile_env env;
   struct profile_pref pref;
   struct profile_asm asmblr;
   struct profile_arch arch;
   struct profile_target tgt;
   void *dest;
   int db_id;

   /* get profile into struct */
   switch (table) {
      case PROFILE_ENV:
         dest = &env; break;
      case PROFILE_PREF:
         dest = &pref; break;
      case PROFILE_ASM:
         dest = &asmblr; break;
      case PROFILE_ARCH:
         dest = &arch; break;
      case PROFILE_TARGET:
         dest = &tgt; break;
   }
   if (! GetProfile(table, id, dest)) { 
      return(0);
   }

   db_id = SwitchDB(db_config->db_id);

   /* apply changes based on Profile type */
   switch (table) {
      case PROFILE_ENV:
         //strncpy(disasm_env.home, env.home, 256);
         strncpy(disasm_env.p1, env.p1, 16);
         strncpy(disasm_env.p2, env.p2, 16);
         strncpy(disasm_env.p3, env.p3, 16);
         strncpy(disasm_env.p4, env.p4, 16);
         strncpy(disasm_env.dbpath, env.dbpath, 256);
         disasm_env.output = env.output;
         break;
      case PROFILE_PREF:
         strncpy(disasm_prefs.pager, pref.pager, 256);
         strncpy(disasm_prefs.editor, pref.editor, 256);
         strncpy(disasm_prefs.debugger, pref.debugger, 256);
         disasm_prefs.options = pref.options;
         break;
      case PROFILE_ASM:
         //strncpy(ext_asm->asm_ttyColor, asmblr.asm_ttyColor, 128);
         //strncpy(ext_asm->data_ttyColor, asmblr.data_ttyColor, 128);
         //strncpy(ext_asm->asm_ttyMono, asmblr.asm_ttyMono, 128);
         //strncpy(ext_asm->data_ttyMono, asmblr.data_ttyMono, 128);
         //strncpy(ext_asm->asm_file, asmblr.asm_file, 128);
         //strncpy(ext_asm->data_file, asmblr.data_file, 128);
         //strncpy(ext_asm->asm_lpr, asmblr.asm_lpr, 128);
         //strncpy(ext_asm->data_lpr, asmblr.data_lpr, 128);
         break;
      case PROFILE_ARCH:
         ext_arch->options = arch.options;
         break;
      case PROFILE_TARGET:
         strncpy(target.path, tgt.path, 256);
         strncpy(target.dbname, tgt.dbname, 256);
         target.size = tgt.size;
         target.entry = tgt.entry;
         strncpy(target.arch,tgt.arch, 32);
         //strncpy(target.asm, tgt.asmblr, 32);
         strncpy(target.format, tgt.format, 32);
         strncpy(target.lang, tgt.lang, 32);
         break;
   }
   SwitchDB(db_id);
   return(1);
}
/* remove profile from DB */
int DeleteProfile(int table, void *id){
   int index, db_id, rv = 1;
   switch (table) {
      case PROFILE_ENV:
         index = PROFILE_ENV_USER;
         break;
      case PROFILE_PREF:
         index = PROFILE_PREF_USER;
         break;
      case PROFILE_ASM:
         index = PROFILE_ASM_NAME;
         break;
      case PROFILE_ARCH:
         index = PROFILE_ARCH_NAME;
         break;
      case PROFILE_TARGET:
         index = PROFILE_TARGET_NAME;
         break;
   }
   db_id = SwitchDB(db_config->db_id);
   if (d_keyfind(index, id) == S_OKAY)
      d_delete();
   else rv = 0;
      
   SwitchDB(db_id);
   return(rv);
}

int AddHistCmd(int id, char *cmd){
   int db_id;
   struct hist_cmd h;
   
   h.id = id;
   strncpy(h.cmd, cmd, 256);
   db_id = SwitchDB(db_config->db_id);
   if (d_keyfind(ID, &id) == S_OKAY)
      d_delete();
   d_fillnew(HIST_CMD, &h);
   SwitchDB(db_id);
   return(1);
}
int GetHistCmd(char *buf){
   int db_id, rv = 0;
   struct hist_cmd h;

   db_id = SwitchDB(db_config->db_id);
   if (d_keyfrst(ID) == S_OKAY) {
      d_recread(&h);
      strcpy(buf, h.cmd);
      d_delete();
      rv = 1;
   }
   SwitchDB(db_id);
   return(rv);
}
