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

#include "main.h"
#include <strstream>
#include <iomanip>
#include <algorithm>
#include <cstdio>

string clcode;

bool is_num(const string str) {
  if(str.empty())
    return false;

  for(unsigned short x = 0; x < str.length(); ++x)
    if(!isdigit(str[x]))
      return false;

  return true;
}

int number_arg(const string str1, string &str2) {
  string::size_type pos;

  if((pos = str1.find('.')) != string::npos) {
    string strA = str1.substr(0, pos);
    str2 = str1.substr(pos + 1, str1.length());

    if(!is_num(strA))
      return 1;
    else
      return atoi(strA.c_str());
  }

  str2 = str1;
  return 1;
}

void log_string(const string str) {
  string str_log;
  str_log = str_time().substr(0, str_time().length() - 1) + " :: " + str + "\n";
  fprintf(stderr, str_log.c_str());
  return;
}

string str_time() {
  return (string)ctime(&current_time);
}

string f_str_box(const string str, const bool line_t = true, const bool line_b = true, const string c_box = "{3") {
  ostrstream ost;
  string str_temp = str, str_temp2, color;
  string::size_type pos;
  short cnt;

  if(line_t)
    ost << c_box << '+' << setfill('-') << setw(71) << "-" << "+\n\r";

  ost.fill(' ');

  while(!str_temp.empty()) {
    if(str_temp.length() > 69) {
      str_temp2 = str_temp.substr(0, 69);
      str_temp2 = str_temp2.substr(0, str_temp2.rfind(' '));
      str_temp.erase(0, str_temp2.length() + 1);
    }
    else {
      str_temp2 = str_temp;
      str_temp.erase(str_temp.begin(), str_temp.end());
    }

    cnt = 0;
    pos = 0;

    while((pos = str_temp2.find('{', pos + 1)) != string::npos)
      cnt += 2;

    if(str_temp2[0] == '{')
      cnt += 2;

    if(!color.empty())
      ost << c_box << "| " << color << setiosflags(ios::left) << setw(69 + cnt) << str_temp2.c_str() << c_box << " |\n\r";
    else
      ost << c_box << "| {0" << setiosflags(ios::left) << setw(69 + cnt) << str_temp2.c_str() << c_box << " |\n\r";

    if((pos = str_temp2.rfind('{')) != string::npos && str_temp2[pos + 1] != '0')
      color = str_temp2.substr(pos, 2);
  }
  
  if(line_b) 
    ost << c_box << '+' << setfill('-') << setw(71) << "-" << "+\n\r{0";

  ost << ends;
  return ost.str();
}

string f_str(const string str) {
  ostrstream ost;
  string str_temp = str, str_temp2;
      
  while(!str_temp.empty()) {
    if(str_temp.length() > 69) {
      str_temp2 = str_temp.substr(0, 69);
      str_temp2 = str_temp2.substr(0, str_temp2.rfind(' '));
      str_temp.erase(0, str_temp2.length() + 1);
    }
    else {
      str_temp2 = str_temp;
      str_temp.erase(str_temp.begin(), str_temp.end());
    }

    ost << str_temp2 << ENDL;
  }
  
  ost << ends;
  return ost.str();
}

string str_bar(const llong stat, const llong max, const string color) {
  short x = stat * 100 / max;

  if(x >= 100)
    return color + "//////////{0";
  else if(x >= 90)
    return color + "/////////{8/{0";
  else if(x >= 80)
    return color + "////////{8//{0";
  else if(x >= 70)
    return color + "///////{8///{0";
  else if(x >= 60) 
    return color + "//////{8////{0";
  else if(x >= 50)
    return color + "/////{8/////{0";
  else if(x >= 40)
    return color + "////{8//////{0";
  else if(x >= 30)
    return color + "///{8///////{0";
  else if(x >= 20)
    return color + "//{8////////{0";
  else if(x >= 10)
    return color + "/{8/////////{0";
  else  
    return "{8//////////{0";
}

void split(string &args, string &arg) {
  if(args.empty())
    return;

  args.erase(0, args.find_first_not_of(' '));
  string::size_type pos;
  
  if(args[0] == '"') {
    if((pos = args.find('"', 1)) != string::npos) {
      arg = args.substr(0, pos);
      args.erase(0, pos + 1);
      return;
    }
  }

  if((pos = args.find(' ')) == string::npos) {
    arg = args;
    args = "";
    return;
  }

  arg = args.substr(0, pos);
  args.erase(0, pos + 1);
  return;
}

string capitalize(const string str) {
  string new_str = str;
  transform(new_str.begin(), new_str.end(), new_str.begin(), tolower);
  new_str[0] = UPPER(new_str[0]);
  return new_str;
}

bool check_name(const string name) {
  if(find(name, "all self someone something the you"))
    return false;

  if(name.find("trenton") != string::npos && name != "Trenton")
    return false;

  if(name.length() < 2 || name.length() > 12)
    return false;

  if(name.find(' ') != string::npos)
    return false;

  unsigned short x;

  for(x = 1; job_table[x].name; ++x)
    if(job_table[x].name == name)
      return false;

  ostrstream ost;

  for(x = 0; x < name.length(); ++x) {
    if(!isalpha(name[x]))
      return false;

    ost.freeze(false);
    ost.seekp(0, ios::beg);
    ost << name[x] << name[x] << name[x] << ends;

    if(name.find(ost.str()) != string::npos)
      return false;
  }

  return true;
}

string colour(const char type) {
  switch(type) {
  default:
  case 'x':
  case '0':     clcode = CLEAR;         break;
  case 'z':     clcode = BLINK;         break;
  case 'b':
  case '4':     clcode = C_BLUE;        break;
  case 'c':
  case '6':     clcode = C_CYAN;        break;
  case 'g':
  case '2':     clcode = C_GREEN;       break;
  case 'm':
  case '5':     clcode = C_MAGENTA;     break;
  case 'r':
  case '1':     clcode = C_RED;         break;
  case 'w':
  case '7':     clcode = C_WHITE;       break;
  case 'y':
  case '3':     clcode = C_YELLOW;      break;
  case 'B':
  case '$':     clcode = C_B_BLUE;      break;
  case 'C':
  case '^':     clcode = C_B_CYAN;      break;
  case 'G':
  case '@':     clcode = C_B_GREEN;     break;
  case 'M':
  case '%':     clcode = C_B_MAGENTA;   break;
  case 'R':
  case '!':     clcode = C_B_RED;       break;
  case 'W':
  case '&':     clcode = C_B_WHITE;     break;
  case 'Y':
  case '#':     clcode = C_B_YELLOW;    break;
  case 'D':
  case '8':     clcode = C_D_GREY;      break;
  case '*':
    switch(num_range(1, 16)) {
    case 1:     clcode = C_RED;         break;
    case 2:     clcode = C_B_RED;       break;
    case 3:     clcode = C_GREEN;       break;
    case 4:     clcode = C_B_GREEN;     break;
    case 5:     clcode = C_YELLOW;      break;
    case 6:     clcode = C_B_YELLOW;    break;
    case 7:     clcode = C_BLUE;        break;
    case 8:     clcode = C_B_BLUE;      break;
    case 9:     clcode = C_MAGENTA;     break;
    case 10:    clcode = C_B_MAGENTA;   break;
    case 11:    clcode = C_CYAN;        break;
    case 12:    clcode = C_B_CYAN;      break;
    case 13:    clcode = C_WHITE;       break;
    case 14:    clcode = C_B_WHITE;     break;
    case 15:    clcode = C_D_GREY;      break;
    case 16:    clcode = CLEAR;         break;
    }
  
    break; 
  case 'a':     clcode = ANSI_RED;     	break;
  case 's':     clcode = ANSI_GREEN;   	break;
  case 'd':     clcode = ANSI_YELLOW;  	break;
  case 'f':     clcode = ANSI_BLUE;    	break;
  case '{':     clcode = '{';           break;
  }
  
  return clcode;
}

bool find(const string str1, const string str2, const bool case_ = false) {
  string str_temp = str2, str = str1;
  string::size_type pos;

  if(!case_) {
    transform(str.begin(), str.end(), str.begin(), tolower);
    transform(str_temp.begin(), str_temp.end(), str_temp.begin(), tolower);
  }

  if((pos = str_temp.find(str, 0)) != string::npos && (!pos || str_temp[pos - 1] == ' '))
    return true;

  return false;
}

string header(const string str, const bool center=false, const string color="{3") {
  ostrstream ost;   

  if(!center)
    ost << color << "+-{#" << str << color << setfill('-') << setw(70 - strlen(str)) << "-";
  else {
    ost << "+";
    short len = (70 - strlen(str)) / 2;

    for(short x = 0; x < len; ++x)   
      ost << "-";
  
    ost << C_B_YELLOW << str << CLEAR;

    for(short x = 0; x < len; ++x)
      ost << "-";

    if(strlen(str) % 2 == 0)
      ost << "-";
    else
      ost << "--";
  }   
        
  ost << "+\n\r" << CLEAR << ends;
  return ost.str();
}
      
string clock(const long minutes) {
  ostrstream ost;
  ost << setfill('0') << setw(2) << (minutes / 60) << ':' << setfill('0') << setw(2) << (minutes % 60) << ends;
  return ost.str();
}

int strlen(const string str) {
  unsigned int len = 0, x;
  
  for(x = 0; x < str.length(); ++x) {
    if(str[x] == '{')
      ++x;
    else   
      ++len;
  }

  return len;
}

string str_comma(const llong number) {
  ostrstream ost;
  ost << number << ends;
  string str = ost.str();
  ost.freeze(false);
  ost.seekp(0, ios::beg);

  for(unsigned short i = 0; i < str.length(); ++i) {
    ost << str[i];

    if((str.length() - (i + 1)) % 3 == 0 && i != str.length() - 1)
      ost << ",";
  }

  ost << ends;
  str = ost.str();
  return str;
}

string dialogue_box(const string name, const string str, const bool more=false) {
  ostrstream ost;
  string::size_type pos;
  short cnt, width=70;

  if(strlen(str) > 70) {
    ost << "{3/-{1" << name << "{3" << setfill('-') << setw(70 - strlen(name)) << "-" << "\\\n\r";
    string str_temp = str, str_temp2, color;
    ost.fill(' ');

    while(!str_temp.empty()) {
      if(str_temp.length() > 69) {
        str_temp2 = str_temp.substr(0, 69);
        str_temp2 = str_temp2.substr(0, str_temp2.rfind(' '));
        str_temp.erase(0, str_temp2.length() + 1);
      }
      else {
        str_temp2 = str_temp;
        str_temp.erase(str_temp.begin(), str_temp.end());
      }

      cnt = 0;
      pos = 0;

      while((pos = str_temp2.find('{', pos + 1)) != string::npos)
        cnt += 2;

      if(str_temp2[0] == '{')
        cnt += 2;

      if(!color.empty())
        ost << "| " << color << setiosflags(ios::left) << setw(69 + cnt) << str_temp2.c_str() << " {3|\n\r";
      else
        ost << "{3| {8" << setiosflags(ios::left) << setw(69 + cnt) << str_temp2.c_str() << " {3|\n\r";

      if((pos = str_temp2.rfind('{')) != string::npos && str_temp2[pos + 1] != '0')
        color = str_temp2.substr(pos, 2);
    }

    if(more)
      ost << '\\' << setfill('-') << setw(66) << "-" << "{7>>>{3--/\n\r{0" << ends;
    else
      ost << '\\' << setfill('-') << setw(71) << "-" << "/\n\r{0" << ends;

    return ost.str();
  }

  ost << "{3/-{1" << name << "{3" << setw(MIN(strlen(str) - strlen(name) + 1, 1)) << setfill('-') << "-" << "\\" << endl;
  width = strlen(str);
  pos=cnt = 0;

  while((pos = str.find('{', pos + 1)) != string::npos)
    cnt += 2;

  if(str[0] == '{')
    cnt += 2;

  ost << "| {8" << setiosflags(ios::left) << setw(width + cnt) << str.c_str() << " {3|\n\r";

  if(more)
    ost << '\\' << setfill('-') << setw(strlen(str) - 3) << "-" << "{7>>>{3--/\n\r{0";
  else
    ost << '\\' << setfill('-') << setw(strlen(str) + 2) << "-" << "/\n\r{0";

  ost << ends;
  return ost.str();
}