#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "global.h"
#include "set.h"
#include "command.h"
#include "window.h"
 
extern CmdList    *find_command();
extern server_ptr gsrv;
extern win_ptr gwin;
 
int warn_of_ignores = DEFAULT_WARN_OF_IGNORES;
char status_window[MAXLEN] = DEFAULT_STATUS_WINDOW;
char status_server[MAXLEN] = DEFAULT_STATUS_SERVER;
char status_query[MAXLEN] = DEFAULT_STATUS_QUERY;
char status_overwrite[MAXLEN] = DEFAULT_STATUS_OVERWRITE;
char status_oper[MAXLEN] = DEFAULT_STATUS_OPER;
char status_mode[MAXLEN] = DEFAULT_STATUS_MODE;
char status_mail[MAXLEN] = DEFAULT_STATUS_MAIL;
char status_insert[MAXLEN] = DEFAULT_STATUS_INSERT;
char status_hold_lines[MAXLEN] = DEFAULT_STATUS_HOLD_LINES;
char status_format[MAXLEN] = DEFAULT_STATUS_FORMAT;
char status_clock[MAXLEN] = DEFAULT_STATUS_CLOCK;
char status_channel[MAXLEN] = DEFAULT_STATUS_CHANNEL;
char status_away[MAXLEN] = DEFAULT_STATUS_AWAY;
char status_user[MAXLEN] = DEFAULT_STATUS_USER;
int show_numerics = DEFAULT_SHOW_NUMERICS;
int show_channel_names = DEFAULT_SHOW_CHANNEL_NAMES;
int show_end_of_msgs = DEFAULT_SHOW_END_OF_MSGS;
int shell_limit = DEFAULT_SHELL_LIMIT;
int send_ignore_message = DEFAULT_SEND_IGNORE_MESSAGE;
int win_scroll = DEFAULT_SCROLL;
int notify_on_termination = DEFAULT_NOTIFY_ON_TERMINATION;
int no_ctcp_flood = DEFAULT_NO_CTCP_FLOOD;
int max_recursions = DEFAULT_MAX_RECURSIONS;
int mail = DEFAULT_MAIL;
int logging = DEFAULT_LOGGING;
char logfile[MAXLEN] = DEFAULT_LOGFILE;
char load_path[MAXLEN] = DEFAULT_LOAD_PATH;
int lastlog_level = DEFAULT_LASTLOG_LEVEL;
int lastlog = DEFAULT_LASTLOG_DEF;
int insert_mode = DEFAULT_INSERT_MODE;
char input_prompt[MAXLEN] = DEFAULT_INPUT_PROMPT;
int input_aliases = DEFAULT_INPUT_ALIASES;
int hold_mode_max = DEFAULT_HOLD_MODE_MAX;
int hold_mode = DEFAULT_HOLD_MODE;
char history_file[MAXLEN] = DEFAULT_HISTORY_FILE;
int history = DEFAULT_HISTORY;
char help_path[MAXLEN] = DEFAULT_HELP_PATH;
int flood_warning = DEFAULT_FLOOD_WARNING;
int flood_users = DEFAULT_FLOOD_USERS;
int flood_rate = DEFAULT_FLOOD_RATE;
int flood_after = DEFAULT_FLOOD_AFTER;
int exec_protection = DEFAULT_EXEC_PROTECTION;
int display = DEFAULT_DISPLAY;
int debug = DEFAULT_DEBUG;
int channel_name_width = DEFAULT_CHANNEL_NAME_WIDTH;
int beep_when_away = DEFAULT_BEEP_WHEN_AWAY;
int beep = DEFAULT_BEEP;
int auto_whowas = DEFAULT_AUTO_WHOWAS;

extern int onoff_toggle(int old, char *str, int *good);
void setshow_lastlog(char *str, int *numb, int type, char *option);
void setshow_onoff(char *str, int *numb, int type, char *option);
void setshow_numeric(char *str, int *numb, int type, char *option);
void setshow_level(char *str, int *numb, int type, char *option);
void setshow_string(char *str, char *numb, int type, char *option);

/* ---------------------------------------------------------------------- */ 
#define SET_DELETE 0
#define SET_SET     1
#define SET_SHOW    2

extern void init_hold_mode(void);
/* ---------------------------------------------------------------------- */ 
void ss_win_hold(char *str, int *numb, int type, char *option)
{
  int ret;

  ret = *numb;
  setshow_onoff(str, numb, type, option);
  if (gwin) {
    gwin->hold_mode = *numb;
    if (*numb && !ret) init_hold_mode();
  }
}

/* ---------------------------------------------------------------------- */ 
void ss_win_hold_max(char *str, int *numb, int type, char *option)
{
  setshow_numeric(str, numb, type, option);
  if (gwin) gwin->hold_mode_max = *numb;
}
/* ---------------------------------------------------------------------- */ 
extern void win_set_logfile(char *, char **, char *);
extern void win_set_log(char *, char **, char *);
/* ---------------------------------------------------------------------- */ 
void ss_logfile(char *str, char *numb, int type, char *option)
{
  char old[MAXLEN], *walk;
  walk = str;
  if (type!=SET_SHOW)
  {
    if (gwin) strcpy(old, gwin->logfile);
    else old[0] = 0;
    win_set_logfile("", &walk, option);
    if (strcasecmp(old, gwin->logfile) != 0)
      setshow_string(str, numb, type, option);
  } else
    setshow_string(str, numb, type, option);
}

/* ---------------------------------------------------------------------- */ 
void ss_log(char *str, int *numb, int type, char *option)
{
  int old = 0;
  char *walk;
  if (!gwin) return;
  walk = str;
  if (type!=SET_SHOW)
  {
    old = (int)gwin->logfile;
    win_set_log("", &walk, option);
    if (old != (int)gwin->logfile)
    setshow_onoff(str, numb, type, option);
  } else
    setshow_onoff(str, numb, type, option);
}

/* ---------------------------------------------------------------------- */ 
CmdList set_list[] =
{
/*
 {"AUTO_UNMARK_AWAY",      setshow_onoff,    (int)&auto_unmark_away      },
*/
 {"AUTO_WHOWAS",           setshow_onoff,    (int)&auto_whowas           },
 {"BEEP",                  setshow_onoff,    (int)&beep                  },
/*
 {"BEEP_ON_MSG",           sethow_level,     (int)&beep_on_msg           },
*/
 {"BEEP_WHEN_AWAY",        setshow_onoff,    (int)&beep_when_away        },
 {"CHANNEL_NAME_WIDTH",    setshow_numeric,  (int)&channel_name_width    },
 {"DEBUG",                 setshow_numeric,  (int)&debug                 },
 {"DISPLAY",               setshow_onoff,    (int)&display               },
 {"EXEC_PROTECTION",       setshow_onoff,    (int)&exec_protection       },
/*
 {"FLOOD_AFTER",           setshow_numeric,  (int)&flood_after           },
 {"FLOOD_RATE",            setshow_numeric,  (int)&flood_rate            },
 {"FLOOD_USERS",           setshow_numeric,  (int)&flood_users           },
 {"FLOOD_WARNING",         setshow_onoff,    (int)&flood_warning         },
*/
 {"HELP_PATH",             setshow_string,   (int)help_path              },
 {"HISTORY",               setshow_numeric,  (int)&history               },
/*
 {"HISTORY_FILE",          setshow_string,   (int)history_file           },
*/
 {"HOLD_MODE",             ss_win_hold,      (int)&hold_mode             },
 {"HOLD_MODE_MAX",         ss_win_hold_max,  (int)&hold_mode_max         },
 {"INPUT_ALIASES",         setshow_onoff,    (int)&input_aliases         },
 {"INPUT_PROMPT",          setshow_string,   (int)input_prompt           },
 {"INSERT_MODE",           setshow_onoff,    (int)&insert_mode           },
 {"LASTLOG",               setshow_lastlog,  (int)&lastlog               },
 {"LASTLOG_LEVEL",         setshow_level,    (int)&lastlog_level         },
 {"LOAD_PATH",             setshow_string,   (int)load_path              },
 {"LOG",                   ss_log,           (int)&logging               },
 {"LOGFILE",               ss_logfile,       (int)logfile                },
/*
 {"MAIL",                  setshow_numeric,  (int)&mail                  },
*/
 {"MAX_RECURSIONS",        setshow_numeric,  (int)&max_recursions        },
 {"NO_CTCP_FLOOD",         setshow_onoff,    (int)&no_ctcp_flood         },
/*
 {"NOTIFY_LEVEL",          setshow_level,    (int)&notify_level          },
 {"NOTIFY_ON_TERMINATION", setshow_onoff,    (int)&notify_on_termination },
*/
 {"SCROLL",                setshow_onoff,    (int)&win_scroll            },
 {"SEND_IGNORE_MESSAGE",   setshow_onoff,    (int)&send_ignore_message   },
/*
 {"SHELL_LIMIT",           setshow_numeric,  (int)&shell_limit           },
 {"SHOW_CHANNEL_NAMES",    setshow_onoff,    (int)&show_channel_names    },
*/
 {"SHOW_END_OF_MSGS",      setshow_onoff,    (int)&show_end_of_msgs      },
/*
 {"SHOW_NUMERICS",         setshow_onoff,    (int)&show_numerics         },
*/
 {"STATUS_AWAY",           setshow_string,   (int)status_away            },
 {"STATUS_CHANNEL",        setshow_string,   (int)status_channel         },
/*
 {"STATUS_CHANOP",         setshow_string,   (int)status_chanop          },
*/
 {"STATUS_CLOCK",          setshow_string,   (int)status_clock           },
 {"STATUS_FORMAT",         setshow_string,   (int)status_format          },
/*
 {"STATUS_HOLD",           setshow_string,   (int)status_hold            },
*/
 {"STATUS_HOLD_LINES",     setshow_string,   (int)status_hold_lines      },
/*
 {"STATUS_INSERT",         setshow_string,   (int)status_insert          },
 {"STATUS_MAIL",           setshow_string,   (int)status_mail            },
*/
 {"STATUS_MODE",           setshow_string,   (int)status_mode            },
/*
 {"STATUS_NOTIFY",         setshow_string,   (int)status_notify          },
 {"STATUS_OPER",           setshow_string,   (int)status_oper            },
 {"STATUS_OVERWRITE",      setshow_string,   (int)status_overwrite       },
*/
 {"STATUS_QUERY",          setshow_string,   (int)status_query           },
/*
 {"STATUS_SERVER",         setshow_string,   (int)status_server          },
 {"STATUS_UMODE",          setshow_string,   (int)status_umode           },
 {"STATUS_USER",           setshow_string,   (int)status_user            },
 {"STATUS_USER1",          setshow_string,   (int)status_user1           },
 {"STATUS_USER2",          setshow_string,   (int)status_user2           },
 {"STATUS_USER2",          setshow_string,   (int)status_user3           },
*/
 {"STATUS_WINDOW",         setshow_string,   (int)status_window          },
 {"WARN_OF_IGNORES",       setshow_onoff,    (int)&warn_of_ignores       },
};
 
#define NUM_SETS (sizeof(set_list) / sizeof(CmdList)) - 1
 
/* ---------------------------------------------------------------------- */
int get_boolvariable(char *var)
{
  CmdList *command;
  int cmd_cnt, *value;
  command = find_command(set_list, NUM_SETS, var, &cmd_cnt);
  if (((cmd_cnt == 1) || (cmd_cnt<0)) && !strcasecmp(command->command, var)) {
    value = (int *)command->varpar;
    if (*value) return TRUE;
    return FALSE;
  }
  return FALSE;
}

int get_intvariable(char *var)
{
  CmdList *command;
  int cmd_cnt, *value;
  command = find_command(set_list, NUM_SETS, var, &cmd_cnt);
  if (((cmd_cnt == 1) || (cmd_cnt<0)) && !strcasecmp(command->command, var)) {
    value = (int *)command->varpar;
    if (*value) return *value;
  }
  return 0;
}

int get_variable(char *var, int *val, char *result)
{
  CmdList *command;
  int cmd_cnt, *value;
  command = find_command(set_list, NUM_SETS, var, &cmd_cnt);
  if (((cmd_cnt == 1) || (cmd_cnt<0)) && !strcasecmp(command->command, var)) {
    value = (int *)command->varpar;
    if (command->cmdfcn == setshow_string) {
      if (val) *val = 0;
      if (result) (void)strcpy(result, (char *)value);
    } else if (command->cmdfcn == setshow_onoff) {
      if (val) *val = *value;
      if (result) (void)sprintf(result, "%s\0", *value?"ON":"OFF");
    }
    else if (command->cmdfcn == setshow_numeric) {
      if (val) *val = *value;
      if (result) (void)sprintf(result, "%d\0", *value);
    }
    else if (command->cmdfcn == setshow_level) {
      if (val) *val = *value;
      if (result) show_level(NULL, *value, 0, result);
    }
    return TRUE;
  }
  if (result) *result = 0;
  if (val) *val = 0;
  return FALSE;
}
 
/* ---------------------------------------------------------------------- */
 
void setshow_onoff(char *str, int *numb, int type, char *option)
{
  char word[MAXLEN];
  int good, ret;

  if (type == SET_SET) {
    (void)grab_word(&str, ' ', word);
    ret = onoff_toggle(*numb, word, &good);
    if (good) *numb = ret;
  }
  say("*** Current value of %s is now %s", option, *numb ? "ON" : "OFF");
}
 
/* ---------------------------------------------------------------------- */
 
void setshow_level(char *str, int *numb, int type, char *option)
{
  int dummy = 0;
  char string[80];
  (void)sprintf(string, "Current value of %s is now: \0", option);
  if ((type == SET_SET) && (*str)) (void)lookup_level(str, numb, &dummy);
  show_level(string, *numb, dummy, NULL);
}
 
void setshow_string(char *str, char *numb, int type, char *option)
{
  if ((type == SET_SET) && (*str)) (void)strcpy(numb, str);
  if (type == SET_DELETE) numb[0] = 0;
  say("*** Current value of %s is now \"%s\"", option, numb);
}
 
void setshow_numeric(char *str, int *numb, int type, char *option)
{
  int bad, loop;
 
  if (type == SET_SET) {
    bad = FALSE;
    for (loop=0;loop<strlen(str);loop++)
      if (!isdigit(str[loop])) bad = TRUE;
    if (bad) say("*** Value of %s must be numeric!", option);
    else *numb = atoi(str);
  } else if (type == SET_DELETE)
    *numb = 0;
  say("*** Current value of %s is now %d", option, *numb);
}
 
/* ---------------------------------------------------------------------- */
void setshow_lastlog(char *str, int *numb, int type, char *option)
{
  setshow_numeric(str, numb, type, option);
  set_list_limit(&(gwin->lastlog), *numb);
}

/* ---------------------------------------------------------------------- */
 
void user_set(char *string)
{
  char word[MAXLEN];
  int cmd_cnt, ret, len, loop, eval, dummy;
  int delete;
  char tempstring[MAXLEN];
  CmdList *command;
 
  delete = SET_SET;
  if (*string == '-')
  {
    delete = SET_DELETE;
    string++;
  }
  (void)grab_word(&string, ' ', word);
  if (!*string && (delete!=SET_DELETE)) delete = SET_SHOW;
  command = find_command(set_list, NUM_SETS, word, &cmd_cnt);
  
  if (cmd_cnt == 0)
    say("*** No such variable \"%s\"", word);
  else if (((cmd_cnt < 0) || (cmd_cnt == 1)) && command)
    command->cmdfcn(string, command->varpar, delete, command->command);
  else {
    len = strlen(word);
    say("*** \"%s\" is ambiguous", word);
 
    for(loop=0;loop<NUM_SETS;loop++)
      if (strncasecmp(word, set_list[loop].command, len) == 0)
        (*set_list[loop].cmdfcn)(word, set_list[loop].varpar, SET_SHOW,
                                 set_list[loop].command);
  }
}
