#include "message.h"

/*

Operations
----------

  Message m;                  // construct empty Message
  Message m ("You see %1");   // Message with no arguments yet
  m << "a road" << 42;        // insert arguments 1 and 2
  m [9] = "a car";            // insert argument 9
  m ['d'] = "some dogs";      // insert argument 'd'

  string s1 = m.str ();       // get Message with arguments

  string s2 = m [2];          // get argument 2
  string s3 = m ['d'];        // get argument 'd'

  m.clear ();                 // clear all arguments
  m.setMsg ("You eat %1");   // change the Message

  // example of doing a Message on-the-fly

  cout << ((Message ("You see %1 and %2") << "food" << "water").str ()) << endl;

*/

string Message::str() const
    { 
    string result;

    string::size_type pos,      // where we are now
                      percent;  // where the % is
       
    for (pos = 0; 
        (percent = msg_.find ('%', pos)) != string::npos;
        pos = percent)
      {
      result += msg_.substr (pos, percent++ - pos); // before the %
  
      // the % might be the last character, so just return it at the end
      if (percent >= msg_.size ())   
        return result + "%";  
  
      // get parameter (eg. %1)
      char c (msg_ [percent++]);
    
      // %% represents a single %
      if (c == '%')
        result += '%';
      else
        {
        vector<string>::size_type argnumber = getSubscript (c);
        // if character in array put in substitute
        if (argnumber >= 1 && 
            argnumber <= MAX_ARG && 
            argnumber <= args_.size ())
          result += args_ [argnumber - 1];
        else
          result += string ("%") + c; // otherwise put character back

        } // end of not %%
      }   // end of for loop - searching for % symbols

      // append rest of string after final argument
      result += msg_.substr (pos); // rest of string
  
      return result;
  } // end of Message::str


  // convert '1' to '9', '0', and 'A' to 'Z' to a number: 1 to 62
int Message::getSubscript (const char c) const
  {
  // convert into subscript (eg. '1' becomes 1, 'a' becomes 11, and so on).
  // cast to unsigned in case it is >= 0x80
  int i = static_cast<unsigned char> (c);

  // 0 becomes 10
  // A becomes 11, B becomes 12 and so on
  // a becomes 37, b becomes 38 and so on
  if (i == '0')
    i = 10; 
  else if (i >= 'A' && i <= 'Z')
    i -= 'A' - 11;    // subtract -11 to add 11 to the result ;)
  else if (i >= 'a' && i <= 'z')
    i -= 'a' - 37;    // subtract -37 to add 37 to the result ;)
  else
    i -= '0';         // '1' to '9' become 1 to 9

  return i;
  };  // end of getSubscript
