#include "mysql_driver.h"
#include "access_control.h"
#include "thread.h"
#include "constants.h"
#include "properties.h"
#include "protocol_config.h"
#include "ta.h"
#include "pc_commands.h"

extern void purify_new_inuse(void);
/*
 * Command functions
 */

int command_show(char *input, GString *output, sk_conn_st *condat) {
  return command_execute(show, "show ", input, output, condat);
} /* command_show() */

int command_set(char *input, GString *output, sk_conn_st *condat) {
  return command_execute(set, "set ", input, output,condat);
} /* command_set() */

int command_stop(char *input, GString *output, sk_conn_st *condat) {
  return command_execute(stop, "stop ", input, output, condat);
}


int command_purify(char *input, GString *output, sk_conn_st *condat)
{
#if 0
  purify_new_inuse();
#else 
  g_string_append(output, "NOP");
#endif
  
  return 0;
}



int command_quit(char *input, GString *output, sk_conn_st *condat) {
    /* Administrator wishes to quit. */
  return PC_RET_QUIT;
} /* command_quit() */

int show_const(char *input, GString *output, sk_conn_st *condat) {
  /* Administrator wishes to show constants. */
  char *result, *name, *cursor;
  int res = 0;
  
  if( strlen(input) > 0 ) {
    cursor = input;
    name = (char *)strsep(&cursor, " ");

    if( (result = CO_const_to_string(name)) != NULL ) {
      g_string_append(output, result);
      wr_free(result);
    }
    else {
      g_string_append(output,  "unknown constant");
      res = PC_RET_ERR;
    }
  }
  else {
    g_string_append(output,  "name required");
    res = PC_RET_ERR;
  }
 
  return res;

} /* show_const() */

int show_consts(char *input, GString *output, sk_conn_st *condat) {
  /* Administrator wishes to show constants. */
  char *s =  CO_to_string();
  g_string_append(output, s);
  free(s);
  return 0;
} /* show_consts() */

int show_props(char *input, GString *output, sk_conn_st *condat) {
  /* Administrator wishes to show properties. */
  char *s =  PR_to_string();
  g_string_append(output, s);
  free(s);  
  return 0;
} /* show_props() */

int show_threads(char *input, GString *output, sk_conn_st *condat) {
  /* Administrator wishes to show thread information. */
  char *s = TA_tostring();
  g_string_append(output, s);
  free(s);  
  return 0;
} /* show_thread() */

int show_whois(char *input, GString *output, sk_conn_st *condat) {
  /* Administrator wishes to show whois query information. */
  PW_interact(condat->sock);
  return 0;
} /* show_whois() */

int show_access(char *input, GString *output, sk_conn_st *condat) {
  /* Administrator wishes to show whois query information. */
  
  char line[128];
  int cnt = 0;
  er_ret_t err; 

  if( act_runtime->top_ptr != NULL ) {
    char *header = AC_to_string_header();
    
    /* print header */
    SK_cd_puts(condat,header);
    wr_free(header);

    cnt = rx_walk_tree(act_runtime->top_ptr, AC_rxwalkhook_print, 
		       RX_WALK_SKPGLU,  /* print no glue nodes */
		       255, 0, 0, condat, &err);
  }
  
  g_string_sprintfa(output, "Found %d nodes\n", cnt);

  return 0;
} /* show_access() */


int show_acl(char *input, GString *output, sk_conn_st *condat) 
{
  /* Administrator wishes to show access control list. */  
  char line[128];
  int cnt = 0;
  er_ret_t err; 

  if( act_acl->top_ptr != NULL ) {
    char *header = AC_acl_to_string_header();
    
    /* print header */
    SK_cd_puts(condat,header);
    wr_free(header);

    cnt = rx_walk_tree(act_acl->top_ptr, AC_rxwalkhook_print_acl, 
		       RX_WALK_SKPGLU,  /* print no glue nodes */
		       255, 0, 0, condat, &err);
  }

  g_string_sprintfa(output, "Found %d nodes\n", cnt);

  return 0;
} /* show_acl() */


int set_acl(char *input, GString *output, sk_conn_st *condat)
{
  int res = 0;
  
  /* first 8 characters ("set acl ") are already skipped */
  if( ! NOERR( AC_asc_acl_command_set( input, "Manual"))) {
    g_string_append(output, "Error!\n");
    res = PC_RET_ERR;
  }
  return res;
}

int set_nodeny(char *input, GString *output, sk_conn_st *condat) {
  /* reset the deny counter in the access tree to 0 (after reenabling) */
  /* first 11 characters ("set nodeny ")  are already skipped */

  if( ! NOERR( AC_asc_set_nodeny(input) )) {
    g_string_append(output, "Error\n");
    return PC_RET_ERR;
  }
  else {
    return 0;
  }
  
} /* set_nodeny() */

int set_updates(char *input, GString *output, sk_conn_st *condat) 
{
  char argstr[17];
  int pause=0, resume=0;
  int res = 0;
 
  if( sscanf(input, "%16s", argstr) == 1) {
    pause = (strcmp(argstr,"pause") == 0);
    resume = (strcmp(argstr,"resume") == 0);
  }
  
  if( !pause && !resume ) {
    g_string_append(output,  "syntax error.");
    res = PC_RET_ERR;
  }
  else {
    /* all params ok. just set the property */
    char *value = pause ? "0" : "1";
    
    if (CO_set_const("UD.do_update", value) == 0) {
      g_string_append(output, "Constant successfully set\n");
    }
    else {
      g_string_append(output, "Could not set\n");
      res = PC_RET_ERR;
    }
  }
  return res;
}


int set_err(char *input, GString *output, sk_conn_st *condat) 
{
  char *erret = NULL;
  int res;

  res = ER_macro_spec(input, &erret);
  g_string_append(output, erret);
  free(erret);

  return res;
}

int show_err(char *input, GString *output, sk_conn_st *condat) 
{
  char *erret = NULL;

  er_print_paths(&erret);
  g_string_append(output, erret);
  free(erret);

  return 0;
}

int show_macros(char *input, GString *output, sk_conn_st *condat)
{
  ER_macro_list(condat);
  return 0;
}

int set_macro(char *input, GString *output, sk_conn_st *condat)
{
  char *name, *body;
  
  if( strlen(input) > 0 ) {
    body = input;
    name = (char *)strsep(&body, " "); 
    
    ER_make_macro( name, body );
  }

  return 0;
}


int stop_query(char *input, GString *output, sk_conn_st *condat) 
{
  int fd, thr;
  /* assume the command is like "stop query 11 17". 
     This is to limit ambiguities (a new thread on the same socket, 
     for example).
. */
  
  if( sscanf(input, "%d %d", &fd, &thr)<2 ) {
    
    g_string_append(output,"error!!");
    return PC_RET_ERR;
  }
  else {
    TA_trigger("whois", fd, thr);
    return 0;
  }
}
