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

#include <cube.h>

void cube::right()
{
  // Adjusting for different coordinate system.
  uint k = cs.k;
  switch (k)
  {
    case 0: k=2; break;
    case 2: k=0; break;
  }

  right(k);
}

void cube::left()
{
  // Adjusting for different coordinate system.
  uint k = cs.k;
  switch (k)
  {
    case 0: k=2; break;
    case 2: k=0; break;
  }

  left(k);
}

void cube::faceleft()
{
  for (uint i=0; i<3; ++i)
    left(i);
}

void cube::faceright()
{
  for (uint i=0; i<3; ++i)
    right(i);
}

void cube::faceup()
{
  for (uint i=0; i<3; ++i)
    up(i);
}

void cube::facedown()
{
  for (uint i=0; i<3; ++i)
    down(i);
}



ostream & cube::print(ostream & os) const
{
  uint index = 0;

  for (uint i=0; i<6; ++i)
  {
    for (uint k=0; k<9; ++k)
    {
      os << (uint) (xi[index]) << " ";
      ++index;
    }
    os << endl;
  }

  return os;
}

istream & cube::read(istream & is)
{

  uint index = 0;

  uint c;

  for (uint i=0; i<6; ++i)
  {
    for (uint k=0; k<9; ++k)
    {
      is >> c;
      xi[index] = (colordef)c;
      ++index;
    }
  }

  return is;
}


void cube::up(uintc i)
{
  assert(i<3);

  uintc k0 = i;
  uintc k1 = k0+3;
  uintc k2 = k0+6;

  colordef a0 = access(5,k0);
  colordef a1 = access(5,k1);
  colordef a2 = access(5,k2);

  access(5,k0) = access(0,k0);
  access(5,k1) = access(0,k1);
  access(5,k2) = access(0,k2);

  access(0,k0) = access(4,k0);
  access(0,k1) = access(4,k1);
  access(0,k2) = access(4,k2);

  uint b0 = 8-i;
  uint b1 = 5-i;
  uint b2 = 2-i;

  access(4,k0) = access(2,b0);
  access(4,k1) = access(2,b1);
  access(4,k2) = access(2,b2);

  access(2,b0) = a0;
  access(2,b1) = a1;
  access(2,b2) = a2;
}

void cube::right(uintc i)
{
  uintc k0 = 3*i;
  uintc k1 = k0+1;
  uintc k2 = k0+2;

  colordef a0 = access(1,k0);
  colordef a1 = access(1,k1);
  colordef a2 = access(1,k2);

  access(1,k0) = access(0,k0);
  access(1,k1) = access(0,k1);
  access(1,k2) = access(0,k2);

  access(0,k0) = access(3,k0);
  access(0,k1) = access(3,k1);
  access(0,k2) = access(3,k2);

  access(3,k0) = access(2,k0);
  access(3,k1) = access(2,k1);
  access(3,k2) = access(2,k2);

  access(2,k0) = a0;
  access(2,k1) = a1;
  access(2,k2) = a2;
}

// No need for efficiency.
void cube::left(uintc i)
{
  right(i);
  right(i);
  right(i);
}

void cube::down(uintc i)
{
  up(i);
  up(i);
  up(i);
}

void cube::reset()
{
  faceset(0,red);
  faceset(1,green);
  faceset(2,blue);
  faceset(3,yellow);
  faceset(4,white);
  faceset(5,orange);
}

void  cube::faceset( uintc i, colordef const c )
{
  uint index = i*9;

  for (uint i=0; i<9; ++i)
    xi[index++] = c;
}


ostream & operator << (ostream & os, cube const & cb)
{ 
  return cb.print(os); 
}

cube::cube()
{
  reset();
}




