/**************************************************************
 * FFTacticsMUD : commands.cpp                                *
 **************************************************************
 * (c) 2002 Damien Dailidenas (Trenton). All rights reserved. *
 **************************************************************/

#include "main.h"
#include <strstream>
#include <iomanip>
#include <set>
#include "mysql/mysql.h"

const struct cmd_type cmd_table[] = {
  { "move",           do_move,        0,      12      },
  { "act",            do_act,         0,      2       },
  { "ok",             do_ok,          0,      2       },
  { "wait",           do_wait,        0,      2       },
  { "look",           do_look,        0,      0       },  
  { "commands",       do_commands,    0,      0       },
//  { "?",            do_help,        0,      0       },
//  { "help",         do_help,        0,      0       },
  { "time",           do_time,        0,      0       },
  { "who",            do_who,         0,      0       },
  { "say",            do_say,         0,      1       },
  { "quit",           do_quit,        0,      1       },
  { "delete",         do_delete,      0,      1       },
  { "buy",            do_buy,         0,      1       },
//  { "sell",         do_sell,        0,      1       },
  { "learn",          do_learn,       0,      1       },
  { "cancel",         do_cancel,      0,      2       },
  { "set",            do_set,         0,      1       },
  { "stats",          do_stats,       0,      0       },
  { "equip",          do_equip,       0,      1       },
  { "remove",         do_remove,      0,      1       },
  { "items",          do_items,       0,      0       },
  { "join",           do_join,        0,      1       },
  { "group",          do_group,       0,      0       },
  { "leave",          do_leave,       0,      1       },
  { "kick",           do_kick,        0,      1       },
  { "yell",           do_yell,        0,      0       },
  { "give",           do_give,        0,      1       },

  { "ooc",		do_ooc,		0, 0 },

  { "setpwd",		do_setpwd,	0, 0 },
  { "setemail",		do_setemail,	0, 0 },

  { "ignore",		do_ignore,	0, 0 },
  { "acknowledge",	do_acknowledge,	0, 0 },
  
  { "finger",         	do_finger,      1 },
  { "freeze",         	do_freeze,      1 },
  { "reboot",         	do_reboot,      1 },
  { "deleteplayers",	do_delplayers,	1 },
  { "force",          	do_force,       1 },
  { "sockets",        	do_sockets,     1 },
  { "beep",           	do_beep,        1 },
  { "disconnect",     	do_disconnect,  1 },
  { "copyover",       	do_copyover,    1 },
  { "shutdown",       	do_shutdown,    1 },
  { "wiznet",         	do_wiznet,      1 },
  { "newlock",        	do_newlock,     1 },
  { "invis",          	do_invis,       1 },
  { "omnipotent",     	do_omnipotent,  1 },
  { "log",            	do_log,         1 },
  { "echo",           	do_echo,        1 },
  { "snoop",          	do_snoop,       1 },
  { "wizlock",        	do_wizlock,     1 },
  { "tell",		do_tell,	1 },
  { "mysql",		do_mysql,	1 },
  { "disable",		do_disable,	1 },
  { "enable",		do_enable,	1 },
  {}
};

void do_commands(CH *ch, string argument = "") {
  unsigned short cmd, cnt = 0;
  set<string> cmd_set;
  set<string>::iterator x;
  string str;
  ostrstream ost;
  
  for(cmd = 0; cmd_table[cmd].name; cmd++)
    if(!cmd_table[cmd].admin)
      cmd_set.insert(cmd_table[cmd].name);

  for(x = cmd_set.begin(); x != cmd_set.end(); ++x) {
    str = "{@" + *x + "{0*";
    ost << setiosflags(ios::left) << setw(16) << str.c_str() << ' ';

    if(++cnt % 5 == 0)
      ost << ENDL;
  }
  
  if(cnt % 5 != 0)
    ost << ENDL;

  if(!ch->admin) {
    ost << ends;
    ch->printf(ost.str());
    return;
  }

  ost << ENDL;
  cnt = 0;
  cmd_set.clear();

  for(cmd = 0; cmd_table[cmd].name; cmd++)
    if(cmd_table[cmd].admin)
      cmd_set.insert(cmd_table[cmd].name);

  for(x = cmd_set.begin(); x != cmd_set.end(); ++x) {
    str = "{^" + *x + "{0@";
    ost << setw(18) << setiosflags(ios::left) << str.c_str() << ' ';

    if(++cnt % 5 == 0)
      ost << ENDL;
  }  

  if(cnt % 5 != 0)
    ost << ENDL;

  ost << ends;
  ch->printf(ost.str());
  return;
}

short cmd_id(DO_FUN *fun) {
  for(short x = 0; cmd_table[x].name; ++x)
    if(cmd_table[x].doFun == fun)
      return x;

  return 0;
}

void do_who(CH *ch, string argument = "") {
  CH *d;
  int cnt = 0, mins = 0, hrs = 0;
 
  for(d = ch_list; d; d = d->next) {
    if(!d->desc || d->desc->connected != CON_PLAYING)
      continue;
 
    ++cnt;
  }

  ostrstream ost;
  ost << " " << str_time().substr(11, 5) << "  up since " << str_boot_time.substr(4, 20) << ", " << cnt << " user" << (cnt > 1 ? "s" : "{0") << ENDL;
  ost << setw(12) << setiosflags(ios::left) << "NAME" << "  " << setw(10) << setiosflags(ios::left) << "JOB" << "  " << setw(3) << "SEX" << "  " << setw(3) << "LVL" << "  " << setw(8) << "LOGIN@" << "  " << setw(6) << setiosflags(ios::left) << "IDLE" << "  " << setiosflags(ios::left) << (ch->admin ? "FROM" : "{0") << ENDL;

  for(d = ch_list; d; d = d->next) {
    if(d->npc || IS_SET(d->act, PLR_INVIS))
      continue;
 
    mins = d->timer % 60;
    hrs = d->timer / 60;
    ost << setw(12) << setiosflags(ios::left) << d->name.c_str() << "  " << setw(10) << setiosflags(ios::left) << job_table[d->cjob].name << "  " << setw(3) << (d->sex ? "F" : "M") << "  " << setw(3) << d->lvl << "  " << setw(8) << d->login.c_str() << "  " << setw(6) << d->idle().c_str() << "  " << (ch->admin ? d->socket : " ") << ENDL;
  }

  ost << ends;
  ch->printf(ost.str());
  return;
}

void do_help(CH *ch, string argument = "") {
  MYSQL mysql;
  MYSQL_RES *res;
  MYSQL_ROW row;
  mysql_init(&mysql);
 
  if(!mysql_real_connect(&mysql, DB_LOC, DB_USER, DB_PASS, DB_NAME, 0, NULL, 0))
    return;
 
  if(argument.empty() || argument.find('/') != string::npos || argument.find('\\') != string::npos || argument.find("'") != string::npos) {
    short cnt = 0;
    ostrstream ost;
    ost << "Usage: help [keyword]\n\r";
    mysql_query(&mysql, "SELECT keyword FROM help_data ORDER BY keyword");
    res = mysql_store_result(&mysql);
 
    while((row = mysql_fetch_row(res))) {
      ost << setw(20) << setiosflags(ios::left) << row[0] << "  ";
 
      if(++cnt % 4 == 0)
        ost << ENDL;
    }
 
    if(cnt % 4 != 0)
      ost << ENDL;
 
    ost << ends;
    ch->printf(ost.str());
    mysql_free_result(res);
    mysql_close(&mysql);
    return;
  }

  ostrstream ost;
  ost << "SELECT * FROM help_data WHERE keyword='" << argument << "'" << ends;
  mysql_query(&mysql, ost.str());
  res = mysql_store_result(&mysql);

  if(mysql_num_rows(res)) {
    row = mysql_fetch_row(res);
    ost.freeze(false);
    ost.seekp(0, ios::beg);
    ost << f_str_box("Keyword: {2" + (string)row[0] + "{0");
 
    if(row[1][0] != '\0') {
      ost << f_str_box("Usage: {2" + (string)row[1] + "{0", false);
      ost << f_str_box("Example: {2" + (string)row[2] + "{0", false);
    }

    ost << f_str_box(row[3], false) << ends; 
    ch->printf(ost.str());
  }
  else
    ch->printf("help: ERROR: No help found on '" + argument + "'.\n\r");

  mysql_free_result(res);
  mysql_close(&mysql);
  return;
}

void do_say(CH *ch, string argument = "") {
  if(argument.empty()) {
    ch->printf("Usage: say [message]\n\r");
    return;
  }

  ch->printf("{mYou say '" + argument + "{m'{0\n\r");
  ch->room->echo("{m" + ch->name + " says '" + argument + "{m'{0\n\r", ch);
  return;
}

void do_stats(CH *ch, string argument = "") {
  if(!argument.empty() && ch->admin) {
    CH *ch2 = NULL;

    if(!(ch2 = get_ch(argument))) {
      ch->printf("stat: ERROR: Target not found.\n\r");
      return;
    }

    ch2->stat(ch);
    return;
  }

  ch->stat(ch);
  return;
}

void do_ooc(CH *ch, string argument = "") {
  if(argument.empty()) {
    ch->printf("Usage: ooc [message]\n\r");
    return;
  }

  for(CH *ch2 = ch_list; ch2; ch2 = ch2->next)
    if(ch2->desc)
      ch2->printf("{7" + ch->name + " OOC '" + argument + "{7'{0\n\r");

  return;
}

void do_look(CH *ch, string argument = "") {
  if(!ch->desc)
    return;

  if(!argument.empty()) {  
    CH *ch2;

    if(!(ch2 = ch->room->ch(argument, ch))) {
      ch->printf("look: ERROR: Target not found.\n\r");
      return;
    }
     
    ch->look(ch2);
    return;
  }

  if(!ch->battle_room) {
    ostrstream ost;
    ost << header(ch->area->name() + " : " + ch->room->name());
    ost << f_str_box(ch->room->description(), false) << ends;
    ch->printf(ost.str());

    if(ch->room->shop)
      ch->room->shop->list(ch);
  }
  else
    ch->print_map(false);

//  ch->room->print_contents(ch);
  return;
}

string cmd_name(const short id) {
  return (string)cmd_table[id].name;
}

void do_yell(CH *ch, string argument = "") {
  if(argument.empty()) {
    ch->printf("Usage: yell [message]\n\r");
    return;
  }

  ch->print_map(true);

  if(ch->battle)
    ch->battle->echo("{7" + ch->name + " yells '" + argument + "{7'{0\n\r");
  else
    ch->room->echo("{7" + ch->name + " yells '" + argument + "{7'{0\n\r");

  return;
}