class Room


/**
 * Title: class Room
 * Description: Class to display room and robot.
 * Copyright (c) 2004 
 * Organisation: UCL
 *
 * @author     Graham Roberts
 * @version    1.2 10/04
 */


import javax.swing.*;
import java.awt.*;


class Room extends JPanel
{
  public final static int NORTH = 1;
  public final static int EAST = 2;
  public final static int SOUTH = 3;
  public final static 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 final static int EMPTY = 0;
  private final static 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);
    }
  }
}