#include "labyrinth.h"

// enum { FREE = 0, WALL = 1, THREAD = 5, GOAL = 2, THESEUS = 3 };

void Labyrinth::ReadFromFile(char * filename){
  ifstream f(filename);
  if( ! f ){
    cerr << "Error opening file " << filename << endl;
    exit(-1);
  }
  string row;
  
  for(int i=0; i<LBR_SIZE; i++){
    getline( f, row );
    if( row.length() != LBR_SIZE ){
      cerr << "Incorrect file format, wrong line size " << i << endl;
      exit(-2);
    }
    for(int j=0; j<LBR_SIZE; j++){
      switch( row[j] ){
      case '0':
	lbr[i][j]=0;
	break;
      case '1':
	lbr[i][j]=1;
	break;
      case '2': 
	lbr[i][j]=2;
	break;
      default:
	cerr << "Incorrect file format, wrong char in line " 
	     << i << " pos " << j << endl;
	exit(-2);
      }
    }
  }
  f.close();
}
  
// in this function we use the cell size

void Labyrinth::Draw( int x, int y, int object ){
  Rect this_cell = MakeRect( CELL_WIDTH*y , CELL_HEIGHT*x, 
			     CELL_WIDTH*(y+1), CELL_HEIGHT*(x+1) );
  switch( object ){ 
  case FREE:
    SetForeColor( 255, 255, 255 );  // white
    PaintRect( this_cell );
    break;
  case WALL:
    SetForeColor( 0, 0, 0 );  // white
    PaintRect( this_cell );
    break;
  case THREAD:
    SetForeColor( 128, 128, 0 );  // white
    PaintRect( this_cell );
    break;
  case GOAL:
    SetForeColor( 255, 0, 0 );  // white
    PaintRect( this_cell );
    break;
  case THESEUS:
    SetForeColor( 0, 0, 255 );
    PaintCircle( CELL_WIDTH*y  + CELL_WIDTH/2, 
                 CELL_HEIGHT*x + CELL_HEIGHT/2, CELL_WIDTH/4 );
    break;
  }
}

void Labyrinth::Put( int x, int y, int obj ){
  if( x < 0 || x >= LBR_SIZE || y < 0 || y >= LBR_SIZE ){
    cerr << "Cell not in labyrinth: " << x << " " << y << endl;
    exit(-3);
  }
  // if( obj != THREAD || obj != THESEUS )
  lbr[x][y]=obj;
  Draw(x, y, obj);
}

void Labyrinth::Draw(){
  ClearDrawing();
  for(int i=0; i < LBR_SIZE; i++ )
    for(int j=0; j < LBR_SIZE; j++ )
      Draw(i, j, lbr[i][j]);
}

// be default, all cells outside the labyrinth contain WALL

bool Labyrinth::Contains(int x, int y, int object){
  if( x < 0 || x >= LBR_SIZE || y < 0 || y >= LBR_SIZE )
    return object == WALL;
  return lbr[x][y] == object;
}


// Theseus is free to move to the free cells, or the the cell
// with the goal
bool Labyrinth::isFree(int x, int y){
  if( x < 0 || x >= LBR_SIZE || y < 0 || y >= LBR_SIZE )
    return false;
  return lbr[x][y] == FREE || lbr[x][y]==GOAL;
}

// embelishing the basic class -- mouse editing
void Labyrinth::Edit(){
    cout << "Click on a wall to raze it\n";
    cout << "Click on a free cell to place a wall\n";
    cout << "Click on the goal to reposition it with the next click\n";
    cout << "Click on cell (0,0)  to finish editing\n\n";

    Point p;
    int x, y;
    bool moving_goal = false;

    while( true ){
        GetClickPoint( p );
        x = p.v/CELL_WIDTH;    // coords are transposed
        y = p.h/CELL_HEIGHT;
        if( x == 0 && y == 0 )
            break;
        // if we are moving the GOAL, place it right away
        if( moving_goal ){
            Put( x, y, GOAL );
            moving_goal = false;
        }
        else {  // not moving the goal
            if( Contains( x, y, GOAL) ){
                Put( x, y, FREE );
                moving_goal = true;
            }
            else if( Contains( x, y, WALL) )
                Put( x, y, FREE );
            else if( Contains( x, y, FREE ) )
                Put( x, y, WALL );
        }     
    }
}

