/* RockKind.h declares class RockKind.
 * 
 *    The value of myRockKindName is one of the following:
 *       IGNEOUS, METAMORPHIC, SEDIMENTARY, 
 ***************************************************************/

#ifndef ROCK_KIND
#define ROCK_KIND

enum RockKindName {KIND_UNDERFLOW = -1,
                   IGNEOUS, METAMORPHIC, SEDIMENTARY,
                   NUMBER_OF_KINDS,
                   KIND_OVERFLOW = NUMBER_OF_KINDS};

#include <iostream>                    // istream, ostream
using namespace std;

class RockKind
{
 public:                               // constructors:
   RockKind();                         //  default value
   RockKind(RockKindName initialRock); //  explicit value

   void read(istream& in);            // input
   void print(ostream& out) const;    // output

   RockKind operator++();              // prefix ++
   RockKind operator++(int);           // postfix ++
   RockKind operator--();              // prefix --
   RockKind operator--(int);           // postfix --

   friend bool operator==(const RockKind& left, const RockKind& right);
   friend bool operator!=(const RockKind& left, const RockKind& right);
   friend bool operator<(const RockKind& left, const RockKind& right);
   friend bool operator>(const RockKind& left, const RockKind& right);
   friend bool operator<=(const RockKind& left, const RockKind& right);
   friend bool operator>=(const RockKind& left, const RockKind& right);

 private:
   RockKindName myRockKindName;
};

// -------- Non-member input --------------------------------------
inline istream& operator>>(istream& in, RockKind& theRockKind)
{
   theRockKind.read(in);
   return in;
}

// -------- Non-member output -------------------------------------
inline ostream& operator<<(ostream& out, const RockKind& theRockKind)
{
   theRockKind.print(out);
   return out;
}

// -------- Initialize me (default-value) -------------------------
inline RockKind::RockKind()
{
   myRockKindName = IGNEOUS;
}

// -------- Initialize me (explicit-value) ------------------------
#include <cassert>
using namespace std;
inline RockKind::RockKind(RockKindName initialRockKindName)
{
   assert(IGNEOUS <= initialRockKindName && 
           initialRockKindName < NUMBER_OF_KINDS);
   myRockKindName = initialRockKindName;
}

// --------- Compare me and anotherRockKind using == ---------------
inline bool operator==(const RockKind& left, const RockKind& right)
{
   return left.myRockKindName == right.myRockKindName;
}

// --------- Compare me and anotherRockKind using != ---------------
inline bool operator!=(const RockKind& left, const RockKind& right)
{
   return left.myRockKindName != right.myRockKindName;
}

// --------- Compare me and anotherRockKind using <= ---------------
inline bool operator<=(const RockKind& left, const RockKind& right)
{
   return left.myRockKindName <= right.myRockKindName;
}

// --------- Compare me and anotherRockKind using >= ---------------
inline bool operator>=(const RockKind& left, const RockKind& right)
{
   return left.myRockKindName >= right.myRockKindName;
}

// --------- Compare me and anotherRockKind using > ---------------
inline bool operator>(const RockKind& left, const RockKind& right)
{
   return left.myRockKindName > right.myRockKindName;
}

#endif

