#ifndef CUBE_H
#define CUBE_H

#include <cassert>
#include <iostream>
using namespace std;

#include <cursor.h>
#include <typedefs.h>
                                                                                
/*!
\brief Cube model.

Imagine a cube fixed. All movements are relative to the 
 front face. For example to look at the left side of the
 cube is really moving the front face turning the cube
 right.

\verbatim
Face Layout
  5
  0 1 2 3
  4

Face
  0 1 2
  3 4 5
  6 7 8
\endverbatim

*/
class cube
{
public:

  /** The cursor is always on the front cube. */
  cursor cs;

  /** Each face of the cube has a color. */
  enum colordef 
  { red, green, blue, 
    yellow, white, orange };

  /** The cube is defined for a fixed position. It is
      composed of 6 faces with 9 elements each where each
      element is associated with a face and position. */
  colordef xi[54];

  /** The cube is initially a completed cube. */
  cube();

  /** Access the k'th face for the i'th 2D matrix value 
      where the face is a 3*3 matrix. */
  colordef & access(uintc k, uintc j)
    { assert(k<6); assert(j<9); return xi[k*9+j]; }

  /** Move i'th row right. */
  void right(uintc i);
  /** Move i'th row left. */
  void left(uintc i);
  /** Move i'th column up. */
  void up(uintc i);
  /** Move i'th column down. */
  void down(uintc i);

  // Move relative to the cursor

  /** Move the row with the cursor right. */
  void right();
  /** Move the row with the cursor left. */
  void left();
  /** Move the column with the cursor up. */
  void up()    { up(cs.j); }
  /** Move the column with the cursor down. */
  void down()  { down(cs.j); }

  // Move cube face

  /** Move the front face cube left. */
  void faceleft();
  /** Move the front face cube right. */
  void faceright();
  /** Move the front face cube up. */
  void faceup();
  /** Move the front face cube down. */
  void facedown();
  
  /** Serialize the cube. */
  ostream & print(ostream & os) const;
  /** Reverse of print, read in the cube. */
  istream & read(istream & in);

  /** Set the face to a uniform color. */
  void faceset( uintc i, colordef const c );

  /** All faces set to a unique color. */
  void reset();

};

ostream & operator << (ostream & os, cube const & cb);



#endif





