#include <iostream> // ostream, cout, endl
#include <cstring>  // strcpy, strcmp
#include <cctype>   // islower, isupper
#include "String.h" // String class

String::String()
{
    // Allocate minimal space
  string_ = new char[1]; 
  string_[0] = 0;        
  std::cout << "[String] Default constructor" 
            << std::endl;
}

String::String(const char *cstr)
{
    // Allocate space and copy
  int len = (int)strlen(cstr);
  string_ = new char[len + 1];
  std::strcpy(string_, cstr);      

  std::cout << "[String] Conversion constructor: " 
            << cstr << std::endl;
}

String::~String()
{
  std::cout << "[String] Destructor: " << string_ 
            << std::endl;
  delete [] string_; // release the array
}

String::String(const String& rhs)
{
  std::cout << "[String] Copy constructor: " 
            << rhs.string_ << std::endl;

  int len = (int)strlen(rhs.string_);
  string_ = new char[len + 1];
  std::strcpy(string_, rhs.string_);
}

String& String::operator=(const String& rhs)
{
  std::cout << "[String] operator=: " 
            << string_ << " = "
            << rhs.string_ << std::endl;

  if (&rhs != this)
  {
    delete [] string_;
    int len = (int)strlen(rhs.string_);
    string_ = new char[len + 1];
    std::strcpy(string_, rhs.string_);
  }
  return *this;
}

std::ostream & operator<<(std::ostream & os, 
                          const String &str)
{
  os << str.string_;
  return os;
}

int String::size(void) const
{
  return (int)strlen(string_);
}

void String::upper(void)
{
  int len = size();
  for (int i = 0; i < len; i++)
    if (std::islower(string_[i]))
      string_[i] -= 'a' - 'A';
}

void String::lower(void)
{
  int len = size();
  for (int i = 0; i < len; i++)
    if (std::isupper(string_[i]))
      string_[i] += 'a' - 'A';
}

bool String::operator<(const String& rhs) const
{
    // if we're 'less' than rhs
  if (std::strcmp(string_, rhs.string_) < 0)
    return true;
  else
    return false;
}

const char& String::operator[](int index) const
{
    // Validate the index
  if ( (index >= 0) || (index < size()) )
    return string_[index];
  else
    return string_[0]; // What to return???

}

char& String::operator[](int index)
{
    // Validate the index
  if ( (index >= 0) || (index < size()) )
    return string_[index];
  else
    return string_[0]; // What to return???

}

String::operator const char *(void) const
{
  return string_;
}