/**
 *  Title:  class Room
 *  Description: Class to display room and robot.
 *  Copyright (c) 2001
 *  Organisation: UCL
 *  @author Graham Roberts 
 *  @version 1.1 10/03
 */
 
import javax.swing.* ;
import java.awt.* ;

class Room extends JPanel
{
  public static final int NORTH = 1 ;
  public static final int EAST = 2 ;
  public static final int SOUTH = 3 ;
  public static final int WEST = 4 ;
  
  private static int DEFAULTPIXELSIZEX = 500 ;
  private static int DEFAULTPIXELSIZEY = 500 ;
  private static int DEFAULTROOMSIZEX = 10 ;
  private static int DEFAULTROOMSIZEY = 10 ;
  
  private int pixelSizeX ;
  private int pixelSizeY ;
  private int roomSizeX ;
  private int roomSizeY ;

  private int robotX = 0 ;
  private int robotY = 0 ;
  private int robotDirection = WEST ;
  
  private int doorWall = EAST ;
  private int doorPosition = 5 ;
  
  private Color wallColour = Color.gray ;
  private Color doorColour = Color.white ;
  private Color robotColour = Color.red ;
  private Color obstacleColour = Color.blue ;
  private Color widgetColour = Color.yellow ;
  
  private static final int EMPTY = 0 ;
  private static final int BLOCKED = -1 ;
  // Any value >0 means one or more widgets is at that location
  private int[][] content ;
 
  public Room(int pixelSizeX, int pixelSizeY, int roomSizeX, int roomSizeY)
  {
    this.pixelSizeX = pixelSizeX ;
    this.pixelSizeY = pixelSizeY ;
    this.roomSizeX = roomSizeX ;
    this.roomSizeY = roomSizeY ;
    content = new int[roomSizeX][roomSizeY] ;
    for (int x = 0 ; x < roomSizeX ; x++)
    {
      for (int y = 0 ; y < roomSizeY ; y++)
      {
        content[x][y] = EMPTY ;
      }
    }
  }
  
  public Room(int sizeX, int sizeY)
  {
    this(DEFAULTPIXELSIZEX,DEFAULTPIXELSIZEY,sizeX,sizeY) ;
  }
  
  public Room()
  {
    this(DEFAULTPIXELSIZEX,DEFAULTPIXELSIZEY,DEFAULTROOMSIZEX,DEFAULTROOMSIZEY) ;  
  }
  
  public int getRoomSizeX()
  {
    return roomSizeX ;
  }
  
  public int getRoomSizeY()
  {
    return roomSizeY ;
  }
  
  public void setRobotPosition(int x, int y, int d)
  {
    robotX = x ;
    robotY = y ;
    robotDirection = d ;
    repaint() ; 
  }
  
  public void setRobotColour(Color c)
  {
    robotColour = c ;
    repaint() ;
  }
  
  public void setDoorPosition(int wall, int position)
  {
    doorWall = wall ;
    doorPosition = position+1 ;
  }
  
  public int getDoorWall()
  {
    return doorWall ;
  }
  
  public int getDoorPosition()
  {
    return doorPosition-1 ;
  }
  
  public void setObstacle(int x, int y)
  {
    content[x][y] = BLOCKED ;
  }
  
  public boolean isObstacleAt(int x, int y)
  {
    return content[x][y] == BLOCKED ;
  }
  
  public void setWidget(int x, int y)
  {
    content[x][y]++ ;
    repaint() ;
  }
  
  public void getWidget(int x, int y)
  {
    if (content[x][y] > 0)
    {
      content[x][y]-- ;
    }
  }
  
  public boolean isWidgetAt(int x, int y)
  {
    return content[x][y] > 0 ;
  }
  
  // This controls the drawing of the window
  // contents.
  public void paint(Graphics g)
  {
    g.setColor(Color.white) ;
    g.fillRect(0,0,this.getWidth(),this.getHeight()) ;
    g.setColor(Color.black) ;
    paintRoom(g) ;
    paintDoor(g) ;
    paintObstacles(g) ;
    paintWidgets(g) ;
    paintRobot(g) ;
  }	
  
  public void beep()
  {
    getToolkit().beep() ;
  }

  public Dimension getPreferredSize()
  {
    return new Dimension(pixelSizeX,pixelSizeY) ;
  }
  
  private void setBlock(Graphics g, int x, int y, Color c)
  {
    int sizeX = getWidth() / (roomSizeX + 2) ;
    int sizeY = getHeight() / (roomSizeY + 2) ;
    g.setColor(c) ;
    g.fillRect(x*sizeX,y*sizeY,sizeX,sizeY) ;
  }
  
  private void drawGrid(Graphics g)
  {
    int sizeX = this.getWidth() / (roomSizeX + 2) ;
    int sizeY = this.getHeight() / (roomSizeY + 2) ;
    g.setColor(Color.lightGray) ;
    for (int i = 0 ; i < roomSizeX+1 ; i++)
    { 
      g.drawLine(i*sizeX,0,i*sizeX,sizeY*(roomSizeY+1)) ;
    } 
    for (int i = 0 ; i < roomSizeY+1 ; i++)
    {
      g.drawLine(0,i*sizeY,sizeX*(roomSizeX+1),i*sizeY) ;
    }      
  }
  
  private void paintRobot(Graphics g)
  {
    int[] xpoints = new int[3] ;
    int[] ypoints = new int[3] ;
    int sizeX = this.getWidth() / (roomSizeX + 2) ;
    int sizeY = this.getHeight() / (roomSizeY + 2) ;
    
    g.setColor(robotColour) ;
    
    switch (robotDirection)
    {
      case NORTH :
          xpoints[0] = sizeX + (robotX * sizeX) ;
          xpoints[1] = xpoints[0] + sizeX ;
          xpoints[2] = xpoints[0] + (sizeX/2) ;
          ypoints[0] = sizeY + (robotY * sizeY) + sizeY ;
          ypoints[1] = ypoints[0] ;
          ypoints[2] = ypoints[1] - sizeY ;
          g.fillPolygon(xpoints,ypoints,3) ;
        break ;
        
      case EAST :
          xpoints[0] = sizeX + (robotX * sizeX) ;
          xpoints[1] = xpoints[0] + sizeX ;
          xpoints[2] = xpoints[0] ;
          ypoints[0] = sizeY + (robotY * sizeY) + sizeY ;
          ypoints[1] = ypoints[0] - (sizeY/2) ;
          ypoints[2] = ypoints[0] - sizeY ;
          g.fillPolygon(xpoints,ypoints,3) ;      
        break ;
        
      case SOUTH :
          xpoints[0] = sizeX + (robotX * sizeX) ;
          xpoints[1] = xpoints[0] + sizeX ;
          xpoints[2] = xpoints[0] + (sizeX/2) ;
          ypoints[0] = sizeY + (robotY * sizeY) ;
          ypoints[1] = ypoints[0] ;
          ypoints[2] = ypoints[0] + sizeY ;
          g.fillPolygon(xpoints,ypoints,3) ;      
        break ;
        
      case WEST :
          xpoints[0] = sizeX + (robotX * sizeX) ;
          xpoints[1] = xpoints[0] + sizeX ;
          xpoints[2] = xpoints[1] ;
          ypoints[0] = sizeY + (robotY * sizeY) + (sizeY/2) ;
          ypoints[1] = sizeY + (robotY * sizeY) ;
          ypoints[2] = ypoints[1] + sizeY ;
          g.fillPolygon(xpoints,ypoints,3) ;      
        break ;
    }
  }
  
  private void paintDoor(Graphics g)
  {
    int x = 0 ;
    int y = 0 ;
    switch (doorWall)
    {
      case NORTH :
        x = doorPosition ;
        y = 0 ;
        break ;
        
      case EAST :
        x = roomSizeX+1 ;
        y = doorPosition ;
        break ;
        
      case SOUTH :
        x = doorPosition ;
        y = roomSizeY+1 ;
        break ;
       
      case WEST :
        x = 0 ;
        y = doorPosition ;
        break ;
    }
    setBlock(g,x,y,doorColour) ;  
  }
  
  private void paintObstacles(Graphics g)
  {
    for (int x = 0 ; x < roomSizeX ; x++)
    {
      for (int y = 0 ; y < roomSizeY ; y++)
      {
        if (content[x][y] == BLOCKED)
        {
          setBlock(g,x+1,y+1,obstacleColour) ;
        }
      }
    }    
  }
  
  private void paintWidgets(Graphics g)
  {
    for (int x = 0 ; x < roomSizeX ; x++)
    {
      for (int y = 0 ; y < roomSizeY ; y++)
      {
        if (content[x][y] > 0)
        {
          setBlock(g,x+1,y+1,widgetColour) ;
        }
      }
    }    
  }
  
  private void paintRoom(Graphics g)
  {
    drawGrid(g) ;
    for (int i = 0 ; i < roomSizeX+2 ; i++)
    {
      setBlock(g,i,0,wallColour) ;
      setBlock(g,i,roomSizeY+1,wallColour) ;
    }
    for (int i = 0 ; i < roomSizeY+2 ; i++)
    {
      setBlock(g,0,i,wallColour) ;
      setBlock(g,roomSizeX+1,i,wallColour) ;
    } 
  }
}