/* Rock.cpp defines the nontrivial members of class Rock.
 ***************************************************************/

#include "Rock.h"

// ------- Read a value into me from in -------------------------
#include <cctype>
#include <string>
using namespace std;

void Rock::read(istream& in)
{
   string rockString;
   in >> rockString;

   for (int i = 0; i < rockString.size(); i++)
      if (islower(rockString[i]))
         rockString[i] = toupper(rockString[i]);

   if (rockString == "BASALT")
      myRockName = BASALT;
   else if (rockString == "DOLOMITE")
      myRockName = DOLOMITE;
   else if (rockString == "GRANITE")
      myRockName = GRANITE;
   else if (rockString == "LIMESTONE")
      myRockName = LIMESTONE;
   else if (rockString == "MARBLE")
      myRockName = MARBLE;
   else if (rockString == "OBSIDIAN")
      myRockName = OBSIDIAN;
   else if (rockString == "QUARTZITE")
      myRockName = QUARTZITE;
   else if (rockString == "SANDSTONE")
      myRockName = SANDSTONE;
   else if (rockString == "SHALE")
      myRockName = SHALE;
   else if (rockString == "SLATE")
      myRockName = SLATE;
   else
   {
      cerr << "\n*** Rock::read(): " << rockString
           << " is not recognized!\n" << endl;
      in.setstate(ios::failbit);
   }
}

// -------- Display my value via out -----------------------------
void Rock::print(ostream& out) const
{
   switch(myRockName)
   {
      case BASALT:     out << "BASALT";    
                       break;
      case DOLOMITE:   out << "DOLOMITE";  
                       break;
      case GRANITE:    out << "GRANITE";  
                       break;
      case LIMESTONE:  out << "LIMESTONE";  
                       break;
      case MARBLE:     out << "MARBLE";  
                       break;
      case OBSIDIAN:   out << "OBSIDIAN";  
                       break;
      case QUARTZITE:  out << "QUARTZITE";  
                       break;
      case SANDSTONE:  out << "SANDSTONE";  
                       break;
      case SHALE:      out << "SHALE";  
                       break;
      case SLATE:      out << "SLATE";     
                      break;
   }
}
// -------- My kind (igneous, metamorphic, ...) ---------------
RockKind Rock::kind() const
{
   switch (myRockName)               // if the rock is...
   {
      case BASALT: case GRANITE:     //   any of these, then
      case OBSIDIAN:                 //      its an igneous rock
         return RockKind(IGNEOUS);
      case MARBLE: case QUARTZITE:   //   any of these, then
      case SLATE:                    //     it's a metamorphic rock
         return RockKind(METAMORPHIC);
      case DOLOMITE: case LIMESTONE: //   any of these, then
      case SANDSTONE: case SHALE:    //     it's a sedimentary rock
         return RockKind(SEDIMENTARY);
   }
}

// -------- My texture (coarse, fine, ...) ------------------
// RockTexture Rock::texture() const
// {
   // ... See Programming Problems ...
// }

// -------- Increment my value (prefix) ----------------------
Rock Rock::operator++()
{
   switch(myRockName)
   {
      case BASALT:     myRockName = DOLOMITE;    
                       break;
      case DOLOMITE:   myRockName = GRANITE;    
                       break;
      case GRANITE:    myRockName = LIMESTONE;  
                       break;
      case LIMESTONE:  myRockName = MARBLE;  
                       break;
      case MARBLE:     myRockName = OBSIDIAN;  
                       break;
      case OBSIDIAN:   myRockName = QUARTZITE;  
                       break;
      case QUARTZITE:  myRockName = SANDSTONE;  
                       break;
      case SANDSTONE:  myRockName = SHALE;  
                       break;
      case SHALE:      myRockName = SLATE;  
                       break;
      case SLATE:      myRockName = ROCK_OVERFLOW;    
   }
   return Rock(myRockName);
}

// -------- Increment my value (postfix) ---------------------
Rock Rock::operator++(int)
{
   RockName savedRockName = myRockName;

   switch(myRockName)
   {
      case BASALT:    myRockName = DOLOMITE;    
                      break;
      case DOLOMITE:  myRockName = GRANITE;    
                      break;
      case GRANITE:    myRockName = LIMESTONE;  
                       break;
      case LIMESTONE:  myRockName = MARBLE;  
                       break;
      case MARBLE:     myRockName = OBSIDIAN;  
                       break;
      case OBSIDIAN:   myRockName = QUARTZITE;  
                       break;
      case QUARTZITE:  myRockName = SANDSTONE;  
                       break;
      case SANDSTONE:  myRockName = SHALE;  
                       break;
      case SHALE:      myRockName = SLATE;  
                       break;
      case SLATE:      myRockName = ROCK_OVERFLOW;    
   }

   return Rock(savedRockName);
}

// -------- Decrement me (prefix) -------------------------------
// -------- Decrement me (postfix) ------------------------------

// Definitions of operator--() and operator--(int) are similar to those
// of operator++() and operator++(int) and are omitted to save space.

